LINUX.ORG.RU
ФорумTalks

Более лучший Лисп

 


3

9

Что бы вы изменили и каким образом в своем любимом/нелюбимом диалекте Лиспа, чтобы он стал ещё лучше? Расскажите обо всех своих грязных фантазиях.

Лиспосрач (и те два унылых анонимуса) не приветствуется.

Перемещено tazhate из development

Объединить пространства имен функций и переменных в elisp. Объяснение в мануале про два шкафа вообще убило. Это полный маразм.

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

Ничего. Я же не Рич Хики, чтобы все ломать.

А что тут можно сломать? Сообщество итак сильно раздроблено и не очень большое (лисп заслуживает сильно большего).

y-combinator
() автор топика
Ответ на: комментарий от buddhist

Ну Схемка хороша, да, особенно Racket, но мне пока хочется статической системы типов (не поверх динамического рантайма как в typed/racket).

y-combinator
() автор топика
Ответ на: комментарий от DeVliegendeHollander

Спасибо, гляну, чето не смотрел в эту сторону.

y-combinator
() автор топика
Ответ на: комментарий от baverman

Да, читал давно уже, после прочтения уверовался, что Лисп-2 — ок, но на практике funcall и #' как-то раздражают своим наличием, Лисп не для тех, кто любит компромисы ;).

y-combinator
() автор топика
Ответ на: комментарий от buddhist

Gambit очень хочу попробовать, никак руки не доходят.

И ещё давно хотел спросить: Kawa можно пользоваться без какой бы то ни было связи с Java? Это же, кажется, просто «лисп на JVM», если я ничего не путаю?

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

без какой бы то ни было связи с Java?

Что вы под этим подразумеваете? Не имея никакого представления о Жабе? Можно, но лучше иметь :)

Gambit очень хочу попробовать

Некоторые вещи в нем крутые, некоторые (такие как неймспейсы и FFI) выглядят как плохо пришитая пятая нога у собаки.

buddhist ★★★★★
()

Большинство «хотелок» скорее касаются особенностей конкретных реализаций.

Любые кардинальные изменения существующей версии лиспа приведут к тому, что данной вариацией будет пользоваться только автор. Это останавливает от кардинальных изменений, не привязанных к конкретной «предметной» области. Возможно, по началу и хотелось «и того, и того, и того», но потом это прошло. На lisper.ru есть топик о некоторых новшествах, частично уже реализованных энтузиастами (или он там один? :))

Можно ещё почитать историю создания стандарта и понять: второму стандарту не быть, по крайней мере в ближайшем будущем. А отход от стандарта при и так скудном сообществе почти автоматически ведёт к изоляции. Я к тому, что первоочередных проблем у каждой конкретной версии и так хватает, чтобы бросить «патчить синицу» и начать гоняться за журавлём.

Ещё один новый? Их и так много: помимо «стандартных» CL и схем (сбоку elisp), всякие clojure, newlisp, picolisp и т.д.

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

Не имея никакого представления о Жабе? Можно, но лучше иметь :)

Спасибо, понял. О Java у меня есть некоторое представление, на уровне небольших несложных программок (немного повыше, чем хеллоуворлды). До «ынтырпрайза», конечно, как до Луны ползком. :) Этого хватит? Или всё же потребуется подтянуть?

DeVliegendeHollander ★★
()

А чего Gambit под Linux'ами не собирается — чето нету билдов?

y-combinator
() автор топика

единственное:

подобно gofix

наличие в каждой среде и каждом сырце под неё - некоей человекочитаемой сигнатуры которая бы позволяло бы обьединить все лисп ветви в один кодовый пул

т.е наличие автоматического приведения кодов разных версий в текущую.

это даёт огромный бурст лиспо-движению

qulinxao ★★☆
()
Ответ на: единственное: от qulinxao

Синтаксис, в т.ч. a.b. Ну и нормальные, простые, человечные циклы for ... break ... continue. try...finally, а не unwind-protect. Короче, привёл бы к поп-культуре.

den73 ★★★★★
()

Схема r5rs. Сделал бы строки списками символов. Добавил бы возможность частичного применения. Убрал бы тошнотворные макросы, заменил бы их на fexprs как в kernel.

anonymous
()

По части общелиспа:

  • расширяемые типы (чтобы create/destroy/print/set/get свои можно было писать, а система их юзала на блобах). Первые три щас хоть как-то можно через CLOS сделать, но очень хочется последних двух
  • расширяемые sequence'ы
  • более полная интеграция CLOS в базовый язык по части типов. Ну или вообще новая объектная система revised.
  • нормальная интроспекция и environment augmentation (чтобы что угодно можно было разобрать по косточкам и собрать обратно)
  • песочница для eval. или даже лучше следующий пункт
  • стандартное подможество функций в кишках среды, чтобы хуки можно было вешать
  • какой-нибудь стандартный интерфейс для расширения компилятора (типа RISC-образного inline VOP assembly, с возможностью определения своих VOP)
  • стандартный лексер
  • inline C
  • CAPI в качестве GUI
  • возможность создания своего менеджера пула/GC
mv ★★★★★
()

Взял бы за основу общелисп (lisp-2), но пересмотрел бы его специальные формы. Чтобы простейшие циклы стали такими формами, и чтобы все специальные формы поддавались бы такому же преобразованию, как вычислительные выражения в f#. Это сделало бы cl-cont намного более эффектинвым. Еще это позволило бы запрограммировать аналог монадической нотации do для более императивного лиспа, что было бы очень полезно для тех же парсер-комбинаторов. Сейчас же принято писать code-walker для каждого случая, что не очень хорошо, а так можно было бы ограничиться только одним code-walker для абсолютно всех монад, т.е. как в f# сейчас.

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

Иногда мне нужны. И как понимаю, самая большая проблема - это конфликт продолжений с рестартами. Хочется и того, и другого одновременно. Трудный выбор.

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

Рестарты это просто функции в динамических переменных, грубо говоря.

Главная проблема у first-class продолжений в том, что они устраняют понятие dynamic-extent, то есть контекста с динамическим временем жизни, а соответственно:

Во-первых, делают невозможной строгую стековую модель исполнения, а это значит, что никакие формы управления потоком вычислений основанные на оной модели(например все коммонлисповые - tagbody+go, block+return-from, throw+catch, unwind-protect) не могут быть нормально реализованы(они, во-первых, просто теряют смысл, а во-вторых их семантику становится легко, случайно и непреднамеренно даже, сломать, использовав продолжения).

Во-вторых, так как у нас теряется понятие dynamic extent, то все first-class и second-class сущности, включая теперь и собственно поток вычислений, получают unlimited extent, а значит мы теперь не можем детерминированно управлять временем жизни неуправляемых ресурсов, навроде файловых дескрипторов.

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

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

Мне больше нравятся контролируемые продолжения. Например, мы говорим, что продолжения могут быть только внутри with-call/cc и/или defun/cc. Только там будет оверхед. Все остальное работает как прежде. Этот подход отличается от принятого в Scheme. Он используется в cl-cont.

Фишка с вычислительными выражениями в том, что не нужно вводить специальную поддержку именно для продолжений. Можно преобразовывать код (через code-walker) для произвольных монад и моноидов. Да, там будет до черта накладных расходов. Да, не будет многих оптимизаций. Но такой код будет строго ограничен рамками with-call/cc или его обобщенного аналога.

Собственно, это и происходит уже сейчас при использовании cl-cont, но он неэффективно раскрывает циклы. Для эффективного раскрытия какие-то примитивы циклов должны были бы быть подняты до уровня специальных форм, как это, грубо говоря, сделано в f#.

Чтобы раскрыть форму unwind-protect, можно было бы завести второе продолжение, которое следовало бы передавать в каждую часть вычисления наряду с основным продолжением. Именно это происходит в f# async при обработке try-finally. Совершенно неясно только, что делать с handler-bind и handler-case, хотя в f# обрабатывается try-with (аналог handler-case). Это все мысли относительно гипотетической лисп-системы, использующей приспособленные для этого специальные формы. Здесь я считаю, что это просто случайное совпадение, что cl-cont уже сейчас умеет раскрывать почти все специальные формы, за исключением unwind-protect и той, что отвечает за handler-bind / handler-case (кажется, первая форма специальная, а вторая - производная).

Умея раскрывать unwind-protect и handler-case, можно было бы закрывать своевременно и файлы, и сокеты. Кстати, в f# есть дополнительная конструкция use! наряду с просто use. Они вполне дружат с async: там можно управлять ресурсами в рамках асинхронного вычисления, построенного фактически на продолжениях (хотя у меня возникали странные баги в редких случаях).

В общем, идея в том, что специальные формы должны быть подобраны таким образом, чтобы после преобразования (будь то монада async или моноиды seq, list, array) сохранялась бы строгая модель исполнения, а также была бы возможность управлять ресурсами. Все это уже реализовано в f#. Только я не представляю себе, как это должно и может ли сосуществовать с рестартами и динамическими переменными. Вполне возможно, что не может, и ничего уже не сделать лучше, чем есть сейчас в common lisp. В некотором смысле, идеал уже, быть может, достигнут.

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

Более лучший Лисп

Не нужно, пишите больше качественных библиотек для существующих, блжад!

gensym ★★
()
Ответ на: комментарий от y-combinator

Ну Схемка хороша, да, особенно Racket, но мне пока хочется статической системы типов

Какие критичные к статической проверке типов задачи решать собрался?

alienclaster ★★★
()

Осторожно, таким путем можно и до Arc-а какого-либо скатиться!

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

handler-* - не спецформы, а просто макросы. Система обработки исключений CL тривиально реализуется на динамических переменных и встроенных формах control flow.

Базис - именно эти спецформы, и с ними все ок, ни больше, ни меньше их не надо. throw, catch, block, return-from, tagbody, go, unwind-protect.

И эти спецформы, являющиеся выражением семантики контроля потока вычислений CL - конфликтуют с продолжениями, как я уже писал. Соответственно, ни с ними, ни со всем что на них построено - ничего сделать нельзя.

btw. «примитивы циклов» это tagbody и go, если на то пошло.

Короче говоря - cl-cont это извращение. А полные продолжения - действительно конфликтуют с семантикой CL, и в языке не нужны. Чтобы действительно сделать хоть какой-то аналог продолжений кроме escape-подвида(который и выражается семантикой CL) - нужно добавлять уровень интерпретации над CL и использовать в нем для них явное представление. По теме интерпретаторов/компиляторов лиспа рекомендую книжку Lisp In Small Pieces.

А нахрена тебе, вообще говоря, они нужны то? Чем не хватает того что есть в CL?

lovesan ★★★
()
Ответ на: комментарий от y-combinator

Конфликтов меньше. В случае с CL у нас макросы «конфликтуют» только с функциями. А в Lisp-1 они бы еще и переменные перекрывали. Пространство переменных зело обширнее, и макросами типа как в CL - в Lisp-1 пользоваться гораздо менее удобно(надо gensym-ить все имена вообще). Это кстати и есть причина по которой в схеме «гигиеничные макросы» ввели.

lovesan ★★★
()

За основу взять CL.

  • Песочницы.
  • Рекурсивные типы. Например, (deftype list-of (item) `(cons ,item (list-of ,item))
  • Специальные функции. Т.е. функции с динамической областью видимости.
  • Стандартный кроссплатформенный гуй.
  • Стандартизация универсальных расширений вроде сокетов и потоков.
naryl ★★★★★
()
Ответ на: комментарий от lovesan

А нахрена тебе, вообще говоря, они нужны то? Чем не хватает того что есть в CL?

Да так, больше для всяких пустяков вроде моделирования. Хотя бы было бы здорово еще иметь парсер-комбинаторы с удобной нотацией do или ее аналогом. Ну, еще реактивное функциональное программирование прикольно, когда можно смешивать async и observable/event. Попробовал - мне понравилось.

На самом деле, это только f# такой особенный. В haskell нотация do более ограниченная (хотя недавно узнал о recursive-do). В scala совсем все глухо, и похоже, что в scala теперь уже никогда не появится ничего уровня вычислительных выражений f#. Так что, общелисп по-прежнему почти впереди планеты всей.

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

Какие критичные к статической проверке типов задачи решать собрался?

Высоконагруженный ентерпрайз веб с возможностью вносить архитектурыне изменения без большой боли. Декларации в CL не предлагать.

y-combinator
() автор топика
Ответ на: комментарий от lovesan

Еще один пример: порождение ленивой последовательности [как правило, неочевидным и запутанным итеративным кодом].

Это можно сделать уже сейчас через мою библиотеку Generic Sequences (ее добавили недавно в QuickLisp). Там есть такой макрос with-seq/cc. Но поскольку он использует with-call/cc, то поэтому имеет те же ограничения, а именно нельзя использовать ни unwind-protect, ни handler-case. Если бы было можно, то тогда было бы легко прочитать файл, да и вернуть его содержимое лениво. Хотя конкретно ленивое возвращение содержимого файла можно закодировать и напрямую (через make-seq), но я говорю об общем случае, когда хорошо было бы захватить на неопределенное время ресурс.

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

Высоконагруженный ентерпрайз веб с возможностью вносить архитектурыне изменения без большой боли. Декларации в CL не предлагать.

Не предлагаю: тут вообще не нужна статическая типизация (даже на уровне деклараций) - только во вред.

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

Конфликтов меньше. В случае с CL у нас макросы «конфликтуют» только с функциями. А в Lisp-1 они бы еще и переменные перекрывали.

Ну меньше это не значит, что их не будет совсем, проблема остается. Да и не понятно, проблема ли это.

Пространство переменных зело обширнее, и макросами типа как в CL - в Lisp-1 пользоваться гораздо менее удобно(надо gensym-ить все имена вообще). Это кстати и есть причина по которой в схеме «гигиеничные макросы» ввели.

Я думаю их ввели скорее потому, что в 99% случаев гигиена нужна.

y-combinator
() автор топика
Ответ на: комментарий от alienclaster

Не предлагаю: тут вообще не нужна статическая типизация (даже на уровне деклараций) - только во вред.

Очень нужна, с нормальным тайпинференсом, чтобы eDSL'ки между собой стыковались правильно.

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

Не предлагаю: тут вообще не нужна статическая типизация (даже на уровне деклараций) - только во вред.

Очень нужна, с нормальным тайпинференсом, чтобы eDSL'ки между собой стыковались правильно.

Нет, не нужна. Статическая типизация - это смерть прототипирования, а успех проекта в современном мире напрямую зависит от скорости расширения функциональности и возможности оказать платную поддержку серьезному кастомеру. Узкие места, где реально требуются какие-то гарантии, обкладывают тестами и сложными внешними системами выводов... даже если они написаны на статике :)

alienclaster ★★★
()

добавил бы в sbcl возможность делать готовые бинарные пакеты со всеми зависимостями, дабы не пользоваться вечно глючным cl-launch

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

Узкие места, где реально требуются какие-то гарантии, обкладывают тестами и сложными внешними системами выводов... даже если они написаны на статике :)

Тесты далеко не панацея — покрывают лишь процентов 10% проблем, и то в том случае если покрытие стремится к 100%, а вот какой-нибудь нежданчик в виде исключения в редко используемой ветке кода обязательно просочится.

А уже не говорю о том, чтобы вносить какие-то серьезные изменения в динамически-типизированную систему — никакой помощи — пока вручную весь сервис не пройдешь все мелкие ошибки не отловишь, а статика сразу материться начинает.

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

типизация покрывает еще меньше чем тесты.

большинство ошибок - в логике, и типизацией никак не ловятся, если это не зависимые типы или что-то вроде того(кстати в CL, что интересно, очень похожая на зависимые типы система)

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

типизация покрывает еще меньше чем тесты.

Это верно если сравнивать 100% покрытие тестами со статикой. На практике, когда покрытие тестами дай бох процентов 10%, а система постоянно меняется — тесты зачастую перестают соответствовать коду и отключаются (т.к. в отличие от системы типов они реально мешают во время активных изменений).

большинство ошибок - в логике, и типизацией никак не ловятся, если это не зависимые типы или что-то вроде того(кстати в CL, что интересно, очень похожая на зависимые типы система)

Ошибки в логике отлавливаются на реальных тестовых прогонах в рамках функционального тестирования, поэтому они будут найдены независимо от наличия или отсутствия статики. А вот ошибки не полного распространения изменений статикой ловятся хорошо, а функциональным тестированием плохо, т.к. редко кто после каждого изменения перепроверяет вообще всё.

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