LINUX.ORG.RU

Альтернатива Emacs Lisp'у

 , ,


1

3

Лисп сам по себе отталкивает часть программистов, а Emacs Lisp, будучи довольно уникальным лиспом, на котором довольно больно писать как в императивном, так и в функциональном стиле, привлекает subset от итак не особо большого количества ценителей S-выражений и макросов.

Предположим, была бы возможность всё то, что сейчас пишется на Emacs Lisp, реализовывать на каком-нибудь С-подобном языке (для конкретики пусть будет Go) - было бы это, по вашему, полезным? Вы бы попробовали?

Запускать Go вместо Emacs Lisp можно было бы при компиляции Go в байткод Emacs Lisp. Технические детали, наверное, пока можно держать в стороне.

Ответ на: комментарий от Oxdeadbeef

А можете, пожалуйста, уточнить, почему именно так? Меня emacs много чем устраивает и я к нему привык.

Не думаю, что Emacs Lisp обязан быть единственным языком, на котором можно «самый расширяемый редактор» подгонять под себя.

quasilyte
() автор топика
Ответ на: комментарий от quasilyte

Странно ты как-то привык, шо ты хочешь туда Го втащить.

slaykovsky ★★★
()
Ответ на: комментарий от quasilyte

Потому что полноценно заменить elisp не получилось даже схемами с коммоном. А ты про левый «гоу».

Не взлетит!

yyk ★★★★★
()
Ответ на: комментарий от yyk

Заменить я не предлагал.

Было предложение рассмотреть возможность компиляции Go в формат, который может быть исполнен Emacs'ом.

quasilyte
() автор топика

у тебя есть идеи, как это реализовать более-менее конструктивные? Можем попробовать. Ради самообразования конечно, оно не взлетит просто в силу традиций

Nicholass ★★★
()
Ответ на: комментарий от Nicholass

Есть попытка: https://github.com/Quasilyte/goism

Пока довольно сыро и, учитывая что я начал рантайм переписывать на самом же транслируемом в lapcode Go, то многие вещи даже в мастере ещё не особо элегантны (разгар переписывания).

Сейчас можно вызывать из Go любую Emacs Lisp функцию, можно типизированную обвязку делать для особо важных функций (чтобы избегать overhead'а на type assertion); в рантайме есть базовая поддержка слайсов.

Из Emacs'а можно все эти функции дёргать. При этом из Go сорцев сохраняются комментарии и идут в docstring. При этом не должно быть коллизий имён, генерируются имена с префиксами пакетов.

Есть некоторые фичи, которые будет реализовать довольно сложно (например, горутины).

quasilyte
() автор топика

Cи-подобные языки тоже, бывают, отталкивают. И golang - тоже. Вообще, нет языков, которые бы не отталкивали. Бессмысленная идея

dave ★★★★★
()
Ответ на: комментарий от dave

Я понимаю, о чём вы. Но не могу принять это аргументом против предоставления выбора.

quasilyte
() автор топика

Предположим, была бы возможность всё то, что сейчас пишется на Emacs Lisp, реализовывать на каком-нибудь С-подобном языке (для конкретики пусть будет Go)

К гайловому Емаксу должно быть несложно прикрутить Яваскрипт (если уже не прикрутили).

было бы это, по вашему, полезным?

Нет.

Вы бы попробовали?

Нет.

Запускать Go вместо Emacs Lisp можно было бы при компиляции Go в байткод Emacs Lisp.

Вы все перепутали. Сладость ГНУ Емакса — в вершках, а не в корешках.

Zmicier ★★★★★
()
Последнее исправление: Zmicier (всего исправлений: 1)

Лисп сам по себе отталкивает часть программистов

Спорное утверждение, сэкспы бывают очень удобны, например для записи сложных математических выражений. Ну и не зря, например, разработчики KiCAD используют их для форматов файлов.

olibjerd ★★★★★
()

Лисп сам по себе отталкивает

Правда твоя.

Предположим, была бы возможность всё то, что сейчас пишется на Emacs Lisp, реализовывать на каком-нибудь С-подобном языке

Из буханки хлеба можно сделать троллейбус ....

Поставь p9p и используй Acme и не мучайся

robot12 ★★★★★
()
Ответ на: комментарий от olibjerd

Возможно мне стоит уточнить посыл того, что вы цитируете. «Не каждому нравится S-выражения, в частности, прямая польская нотация». Преимущества формата я не пытался преуменьшить. Плюс варить скобочки можно по-разному: в clojure скобочек, как правило, меньше.

quasilyte
() автор топика
Ответ на: комментарий от Hertz

Вместо модулей можно делать Emacs Lisp пакеты, оформленные по правилам, с doc-строками и сигнатурами для eldoc. Это для пользователя (и автора пакета), как я полагаю, удобнее.

Модули я уже трогал. Немного оффтопик: там при каждом вызове сишной функции происходит аллокация (даже если функция не делает ничего), что несколько расстраивает.

quasilyte
() автор топика

SciTE давно уже есть.

ados ★★★★★
()
Ответ на: комментарий от quasilyte

Немного оффтопик: там при каждом вызове сишной функции происходит аллокация (даже если функция не делает ничего), что несколько расстраивает.

Почему тебя это волнует?

anonymous
()

Чего вы с этим Го носитесь?

cnupm
()

Запускать Go вместо Emacs Lisp можно было бы при компиляции Go в байткод Emacs Lisp

Это глупо, потому что проблемы elisp как раз лежат в области реализации - тормознутость, однопоточность и т.д.

а Emacs Lisp, будучи довольно уникальным лиспом,

Ничего суперуникального в нем нет. Основная «сложность» это уникальность платформы - буферы, exscursion, и т.д. Переход на Го этого всего никак не изменит.

no-such-file ★★★★★
()

реализовывать на каком-нибудь С-подобном языке (для конкретики пусть будет Go) - было бы это, по вашему, полезным?

Дело не в С-подобности или синтаксисе, а в возможостях метапрограммирования. Red вполне подойдет, только емакс морально уже устарел (хоть и нет аналогов достойных) и стоит сразу делать что-то новое.

loz ★★★★★
()
Ответ на: комментарий от quasilyte

Правило Гринспена

Было предложение рассмотреть возможность компиляции Go в формат, который может быть исполнен Emacs'ом.

Отлично, вы хотите написать компилятор elisp'а на Go.

Camel ★★★★★
()
Ответ на: комментарий от yyk

CL летит

Потому что полноценно заменить elisp не получилось даже схемами с коммоном.

Я немного не специалист по Emacs и Lisp, но разве с CL совсем-совсем не получилось? Насколько я (возможно неверно) знаю для Emacs'а можно писать модули на CL и подключать их используя (require 'cl). Или я опять всё перепутал?

Camel ★★★★★
()
Ответ на: CL летит от Camel

(require 'cl)

Так делать не рекомендуется. Вместо этого нужно использовать cl-lib, в которой все функции перффиксируются cl-. Да и это имплементация CL на emacs lisp, которая исполняется всё на той же машине, а основное преимущество cl (по сравнению с elisp) не в самом языке, а как раз в реализациях виртуальных машин, которые заметно более производительные в большинстве и позволяют использовать многопоточность.

feofan ★★★★★
()
Ответ на: комментарий от no-such-file

Общая оценка идеи мне ясна (ваша и других участников). За прямоту и честность - спасибо.

На ваше сообщение отвечу не ради переубеждения, а для того, чтобы убедиться, что мы друг друга всё-таки правильно поняли.

Это глупо, потому что проблемы elisp как раз лежат в области реализации - тормознутость, однопоточность и т.д.

Есть разные проблемы. Производительность и однопоточность - это один вид проблем. Их я решать как минимум пока не собираюсь. Нужно как-то scope проекта определить, «просто сделать хорошо» у меня не получится.

Лично я вижу, что можно получить следующие выгоды при возможности писать под Emacs на Go:

1. бесплатный тулинг (крутой autocomplete, рефакторинг через gorename, линтеры и прочее).

2. пакеты (особенно здорово для приватных функций, можно давать короткие названия).

3. overhead-free структуры из 1 атрибута (unboxed значения) и другие оптимизации, которые проще выполнять в статически типизируемом языке.

4. другой синтаксис.

5. слайсы (расширяемые массивы) как самый фундаментальный контейнерный тип. Он для многих вещей подходит лучше, чем списки.

Ничего суперуникального в нем нет. Основная «сложность» это уникальность платформы - буферы, exscursion, и т.д. Переход на Го этого всего никак не изменит.

Субъективно, мне не нравится как выглядит императивщина на Emacs Lisp. На том же racket и функционально, и императивно писать приятнее.

Я в прошлом на Emacs Lisp в том числе и небольшие скрипты писал, чтобы было можно их интерактивно гонять и хранить state в самом Emacs. Вот мне видится, что на Go это ложилось бы неплохо.

quasilyte
() автор топика
Ответ на: Правило Гринспена от Camel

Я пишу сильно более простую вещь.

Весь frontend даёт стандартная библиотека Go.

Остаётся рантайм, который можно на том же лиспе написать, да преобразование AST в lapcode.

Этот lapcode в байткод перегонит сам компилятор Emacs Lisp'а, да ещё и низкоуровневые оптимизации выполнит.

quasilyte
() автор топика

Вместо Emacs Lisp можно заюзать Guile - официально рекомендованный GNU язык для скриптинга.

nihirash ★★★
()

будучи уникальным лиспом, на котором довольно больно писать как в императивном, так и в функциональном стиле

Ты CL с хацкилем не попутал часом?

kawaii_neko ★★★★
()

- было бы это, по вашему, полезным?

нет

Вы бы попробовали?

нет

Deleted
()
Ответ на: комментарий от anonymous

Почему тебя это волнует?

Если вам действительно интересно, я вам отвечу.

Это на практике делает невозможным эффективную реализацию, например, расширяемых массивов на C с лисповой мордой. На каждый вызов вашего `ext-vector-ref` будет аллокация, из-за чего в разы будет медленнее, чем в случае с нормальной встроенной функцией. Разница в скорости на порядки, что-то близ «в сотни раз». Для конкретных цифр мне нужно будет найти код, который это проверял.

Реализовать растущие массивы можно и поверх векторов лиспа, на самом же лиспе, но тот же slice из Go эффективно реализовать будет сложнее. Если очень интересно, могу поделиться, почему.

quasilyte
() автор топика
Ответ на: комментарий от quasilyte

I don't get it, sorry.

Действительно, я как-то неправильно спросонья распарсил твою фразу. Почему-то прочитал как «на CL больно писать в императивном стиле».

kawaii_neko ★★★★
()
Ответ на: комментарий от quasilyte

1. бесплатный тулинг (крутой autocomplete, рефакторинг через gorename, линтеры и прочее).

Всё это прекрасно работает для elisp.

2. пакеты (особенно здорово для приватных функций, можно давать короткие названия).

То, что emacs lisp отсутствуют нэймспейсы печально, но обходится конвенцией именования. А для тех, кому больно так писать есть https://github.com/Malabarba/nameless

3 верно лишь отчасти

4. другой синтаксис.

Вкусовщина.

5. слайсы (расширяемые массивы) как самый фундаментальный контейнерный тип. Он для многих вещей подходит лучше, чем списки.

Слайсы подходят для активного преобразования AST? Списками набор типов emacs lisp'a не ограничивается.

feofan ★★★★★
()
Ответ на: комментарий от quasilyte

Реализовать растущие массивы можно и поверх векторов лиспа, на самом же лиспе, но тот же slice из Go эффективно реализовать будет сложнее. Если очень интересно, могу поделиться, почему.

Интересно, поделись.

feofan ★★★★★
()
Ответ на: комментарий от feofan

Но ведь не всё, что вкусовщина - плохо.

Слайсы подходят для активного преобразования AST?

Хороший point, но я всё-таки не так часто именно с AST работаю в Emacs коде. Когда макросы пишу - само собой приходится, но я скорее склонен полагать, что макросов мне бы стоило писать поменьше, а функций (или defsubst функций, если так нужен inlining) - побольше.

Я считаю, что нужны и списки, и растущие массивы (причём желательно с возможностью иметь разделяемый «срез»).

Но если говорить о «структуре по умолчанию», которая в 90% мест просочится, то списки мне в императивном коде не особо нравятся (большая часть кода на Emacs Lisp, имхо, пишется именно через циклы и изменения состояния).

quasilyte
() автор топика
Ответ на: комментарий от quasilyte

Но если говорить о «структуре по умолчанию», которая в 90% мест просочится, то списки мне в императивном коде не особо нравятся (большая часть кода на Emacs Lisp, имхо, пишется именно через циклы и изменения состояния).

Там, где всё равно идёт обход всего списка (то, как чаще всего использую списки в emacs lisp я) выигрыша от использования массива не будет.

feofan ★★★★★
()
Ответ на: комментарий от feofan

Допустим, мы начнём с представления вида {data, len, cap}. Data будет вектором. Вместо списка возьмём improper list, где у нас нет финального nil, чтобы немного экономить память:

(cons data (cons len cap))

Если интересно, почему не вектор - тут надо в дизассемблер смотреть. Доступ к спискам из 2-3 элементов - очень эффективный. Чем ближе к голове списка, тем эффективнее. Data чаще всего используется, поэтому он в начале списка.

Операции get/set будут очень эффективными. У нас будет тот же aset/aget, но с overhead на (car slice).

Но что будет, когда вы берёте subslice? В C вы могли бы data сделать указателем и сместить его, куда нужно. Адресация была бы такой же, 0-based. В нашем случае это невозможно, что приводит к необходимости хранить ещё и offset:

(cons data (cons offset (cons len cap)))

Для каждого get/set теперь нужно к индексу прибавлять offset.

Для обычного вектора:

<vector>
<index>
aref
Для slice без поддержки offset:
<slice>
car
<index>
aref
Для slice с поддержкой offset:
<slice>     ;; <slice>
dup         ;; <slice slice>
car         ;; <slice data>
stack-ref 1 ;; <slice data slice>
cdr         ;; <slice data slice.cdr>
car         ;; <slice data offset>
<index>     ;; <slice data offset index>
plus        ;; <slice data real-index>
aref        ;; <slice elem>
stack-set 1 ;; <elem>

Операция set элемента так же разбухает. Как реализовать более эффективно я пока не знаю.

Бенчмарки проводил. Если вместо вектора использовать списки, то мы на всех операциях будем проигрывать на порядки. Если вместо improper списка для slice'а использовать вектор, теряем около 10% производительности + const vector из-за индексов может увеличиться.

quasilyte
() автор топика
Ответ на: комментарий от feofan

А ещё всякие вытекающие проблемы. Насколько мне известно, в Emacs'е нет эффективной функции для копирования элементов из диапазона вектора в другой вектор.

quasilyte
() автор топика
Ответ на: комментарий от quasilyte

Насколько мне известно, в Emacs'е нет эффективной функции для копирования элементов из диапазона вектора в другой вектор.

substring

feofan ★★★★★
()
Ответ на: комментарий от feofan

substring

Наверное криво выразился. У вас уже есть 2 вектора (потенциально больших) и нужно из одного перекопировать часть элементов во второй. При этом offset может быть ненулевой.

quasilyte
() автор топика
Ответ на: комментарий от feofan

А почему бы не использовать вместо improper list вектор или hash table? тогда set и get будут работать за O(1).

Для хранения элементов используется вектор. improper list используется для представления структуры (data+offset+len+cap). То есть get/set O(1).

quasilyte
() автор топика
Ответ на: комментарий от quasilyte

Это на практике делает невозможным эффективную реализацию, например, расширяемых массивов на C с лисповой мордой.

Лол. Зачем это делать на практике? Какое _таким_ массивам применение? Ну скопируй данные из массива C в массив Lisp и будет счастье.

anonymous
()
Ответ на: комментарий от quasilyte

Наверное криво выразился. У вас уже есть 2 вектора (потенциально больших) и нужно из одного перекопировать часть элементов во второй. При этом offset может быть ненулевой.

Не выглядит как такая уж частая задача

feofan ★★★★★
()
Ответ на: комментарий от feofan

[data offset len cap]

Я не спорю, что это корректное представление, но склонен полагать, что для N=3 доступ из списка (учитывая инструкции Emacs Lisp VM) эффективнее. Атрибут «cap» используется реже всех, поэтому даже при N=4 тут выбран список.

Это не критичный аспект реализации, как мне кажется. Наиболее печальное - это требование арифметики со смещением для get/set и... листинг, который я привёл выше, не на 100% конформен к спецификации Go. Нужно ещё добавлять проверку границ массива (ведь у нас может быть слайс, у которого длина меньше, чем размер underlying Emacs Lisp вектора).

quasilyte
() автор топика
Ответ на: комментарий от SZT

Нужен лисп

С такой формулировкой я спорить не могу. Лисп действительно нужен.

Пытаюсь учитывать контекст: «Если и делать альтернативу, то она должна быть лиспом».

Это была ваша мысль? Мне кажется, что слишком много лиспов не бывает, но и не лисп добавить тоже можно.

quasilyte
() автор топика
Ответ на: комментарий от L29Ah

Не слышал раньше о таком. Вы его использовали?

Возможно это удобный способ улучшить владение Haskell, если там такая же достойная интеграция, как у лиспа в Emacs.

quasilyte
() автор топика
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.