LINUX.ORG.RU

Ищутся библиотеки для Common Lisp

 


0

2

Ищу следующие вещи под пермиссивными лицензиями:

1. Реализацию неограниченного call/cc. Пока нашёл в Arnesi интерпретатор с call/cc и он вроде бы работает, но желателен всё же нативный код. Я знаю проблемы, связанные с call/cc в лиспе, но в данном случае я готов на компромиссы, можно мне не постить Ловесана.

2. cons как интерфейс. Т.е. должна быть возможность перекрыть примитивы car,cdr и cons и на базе этого должна быть построена библиотека лисповых функций работы со списками (и с последовательностями, в той части, где это касается списков). А также должна быть возможность в инспекторе SWANK скрыть реализацию, чтобы это было похоже на список. Пока не искал.

3. Структуры и массивы с состоянием, зависимым от времени, с возможностью откатить время до какой-то точки и начать с начала. Скажем, должна быть переменная *текущий-тик-часов* и при присваивании поля как-то запоминается, в какой тик это было сделано, и тик увеличивается на один. Дальше есть возможность эффективно узнать значение поля на любой тик. Также должна быть возможность сказать, «все тики, начиная с такого-то, более невалидны». И начать время заново.

★★★★★

дык ведь неограниченный call/cc не совместим с cl

anonymous
()

По пункту 3. Тут надо использовать чистые функциональные структуры, обернутые в мутабельную ссылку. Учитывая, что современное поколение лисперов в большинстве своем почему-то люто ненавидит функциональное программирование, вряд ли такая готовая библиотека существует в готовом виде, но написать ее вполне можно.

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

Вот предыдущая тема: Существует ли Common Lisp с полнофункциональным call/cc?

Мне не нужен полный CL, мне достаточно совместимого подмножества. Я готов отказаться от unwind-protect для данного случая.

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

Тем не менее try-finally и try-with (catch) вполне себе реализуются через продолжения. Только на других языках.

Вообще, когда я увидел твою тему, то у меня первая мысль возникла «Почему не Haskell?» Еще F# бы подошел с его Async. На счет Scala я бы сильно засомневался.

А чем cl-cont не угодил тебе?

Для лиспа не знаю ничего лучше. Он вполне себе использует довольно большое подмножество CL. Правда, cl-cont порождает чудовищно неэффективный код по сравнению с аналогичным на Haskell и F#, но на безрыбье и рак - щука)

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

Недолюбливаю GPL-подобные лицензии, больше ничем. Говорят, есть какая-то SBCL-специфичная реализация продолжений. Кто даст ссылку?

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

Вот тут http://permalink.gmane.org/gmane.lisp.steel-bank.devel/7569 написано, что на этапе IR1 SBCL делает CPS преобразование.

Есть ещё вот такая работа - пока даже не понял про что:

http://arxiv.org/ftp/arxiv/papers/1510/1510.03057.pdf

Есть sb-heapdump , который теоретически можно попробовать использовать, чтобы буквально запоминать состояние треда и потом вспоминать его.

cl-store и fasl-файлы можно использовать для сериализации набора лисповых объектов.

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

Только на других языках.

Вероятно, только на руби и scheme, не считая экзотику. Что есть еще языки, в которых есть продолжения? (имеется в виду настоящие, а не эмуляция через CPS)

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

Разовью дальше твою гениальную идею, доведя ее немного до абсурда, чем она сама по себе уже отчасти является.

Тогда предлагаю писать прямо в машинных кодах - это где байтики из цифр. Нафиг этот ассемблер, который эмулирует машинный коды через какие-то мнемонические названия! Понятное дело, что на Си и Си++ даже не стоит думать писать, потому что они эмулируют уже свою исполняющую машину, которая еще дальше от машинных кодов)) А может, вообще, надо на микрокоде процессора тогда писать? Знаешь, тоже интересная мысль)

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

Что ты имеешь в виду? Это асинхронные исключения, которые кидаются в другой поток, или близкая этому отмена уже запущенного асинхронного вычисления? Это все уже есть в Haskell и F#.

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

Ещё была мысль взять eval из SBCL и научиться сохранять его состояние. Но он опирается на обычный стек, так что не вышло. Пока план такой:

1. Arnesi реализует undelimited продолжения.

2. Допилить глубокое копирование environment (там какая-то проблема, к ночи уже не разобрать).

3. Положить с прибором на то, что интерпретатор.

4. Если будет медленно - попытаться взять код из GC SBCL - научиться копировать нативные стеки. Это уже очень сложно для меня, но зато очень круто :) Если Monk скажет, какой хак на тему продолжений он видел для SBCL, это может помочь делу. Я пока нашёл sb-heapdump, но он довольно давно был - лет 8 назад, с тех пор много воды утекло... И я пока не понял, относится ли он вообще к делу.

den73 ★★★★★
() автор топика
Последнее исправление: den73 (всего исправлений: 1)
Ответ на: комментарий от filequest

Затем, что код, требующий обработки, императивен. Это парсер ЯП. Я хочу, чтобы один и тот же парсер был и для транслятора, и для раскраски в редакторе. Для раскраски нужно запоминать через каждые N строк состояние парсера и перезапускать его, если что-то поменялось. Перезапускать придётся одно и то же состояние много раз. В императивном случае для этого просто продолжения не подходят, нужно именно копирование состояния. Не то, чтобы совсем глубокое, но нужно создать копию состояния, полностью независимую от образца.

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

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

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

Т.е., может оказаться, что невозможно использовать один и тот же парсер и для транслятора, и для раскраски.

den73 ★★★★★
() автор топика
Последнее исправление: den73 (всего исправлений: 1)
Ответ на: комментарий от den73

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

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

Парсер читает текст (последовательность лексем, не суть) и выдаёт аллею из деревьев. Та часть аллеи, которая создана до точки, где стоит курсор - это я и понимаю под состоянием.

den73 ★★★★★
() автор топика

Обкатали же идею call/cc на схеме и признали что ее нельзя эффективно реализовать. Вопрос. Нахрена теперь тащить call/cc в CL.

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

А мне не надо эффективно. Мне надо, чтоб работало. После редакторов на JavaScript, по-моему, вообще смешно ставить слово «эффективность» рядом со словом «редактор».

den73 ★★★★★
() автор топика
Последнее исправление: den73 (всего исправлений: 1)
Ответ на: комментарий от anonymous

Обкатали же идею call/cc на схеме и признали что ее нельзя эффективно реализовать.

С чего бы? В том же CPS вызов продолжения = обычный функциональный вызов.

anonymous
()
12 мая 2016 г.

Screamer теперь под MIT и в нём есть якобы эффективная реализация CPS.

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

Я в код не смотрел, но в доках у них написано, что перехватываются setf-ы к внешним ресурсам и пишется трэк на случай отката. Где такое советуют если не секрет? Ну и сам screamer это более prolog c возможностями лиспа, чем наоборот.

antares0 ★★★★
()
Последнее исправление: antares0 (всего исправлений: 1)
Ответ на: комментарий от antares0

Я не знаю, где это советуют, но я не вижу в этом проблемы - половина СУБД реализована именно таким способом. Если это будет мешать, то можно и поменять.

Главное, я уже выяснил, что отладчик нормально работает с таким кодом:

(eval-when (:compile-toplevel :load-toplevel)
  (require :screamer))

(in-package :screamer-user)

(defun f0 (x)
  (if (oddp x)
      x
      (progn
        (break)
        (fail))))

(defun f1 ()
  (all-values
       (let ((x (either 1 2 3 4)))
         (f0 x))))

Хотя в стеке есть некоторое количество «мусора», в целом можно работать. И даже SBCL-ский степпер позволяет походить по коду после break. И плюс нативный код - неплохо для начала.А то, что я раньше хотел сделать с Arnesi, скорее всего, можно было бы отлаживать только принтами или писать свой отладчик. И это был бы интерпретатор (в котором я уже успел исправить одну багу за пару часов игры в него).

Также у нас есть библиотека для реализации «версионного состояния». Она пока в зачаточном состоянии, но дизайнерские вопросы вроде уже решены. Возможно, что нам и не будет нужен откат setf.

Я не соглашусь, что screamer - это пролог. По-моему, это именно лисп с элементами пролога.

den73 ★★★★★
() автор топика
Последнее исправление: den73 (всего исправлений: 2)
Ответ на: комментарий от den73

Monk

Треды на базе CPS не могут быть легковесными. В том смысле, что CPS на (iter (for i in 1 10) (collect i)) замедляет выполнение в десяток раз.

Либо надо использовать что-то вроде https://github.com/zkat/chanl или (лучше) http://orthecreedence.github.io/blackbird/ ,
либо использовать реализацию Scheme (так как переход для оптимизации CPS -> байткод — всего лишь вопрос времени). Если принципиально использовать CL в качестве среды работы, можно взять ftp://ftp.cs.indiana.edu/pub/scheme-repository/imp/scheme88.tar.gz (это реализация Scheme на CL)

Я верно понимаю, что оба варианта с асинхронщиной всё равно потребуют переделки всего кода в event-driven, а chanl ещё и зависит от внешней библиотеки? Такое не хочу я. Мне совершенно не понравилось event-driven программирование, которого я поимел немало, когда писал clcon.

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

Касабельно схемы - это слишком монструозный вариант. Тем более, схемы, написанные на CL, обычно не имеют полноценных continuations, либо являются интерпретаторами. Хотя я сейчас посмотрю.

Я имею в виду, реализовать с помощью CPS идею сохранения и восстановления стека.

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

Там написано, что мы должны все изменения отправлять обратно в Indiana University. Я не спец, но я бы не сказал, что это похоже на пермиссивную лицензию.

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

Там написано, что мы должны все изменения отправлять обратно в Indiana University.

Так это относится только к самому коду scheme88.

Users of this software agree to make their best eforts (a) to return
to Indiana University Computer Science Department Scheme Group any
improvements or extensions that they make, so that these may be included
in future releases;
Кроме того «make their best eforts» <> «must». В том смысле, что если GPL запрещает использовать лицензированные под GPL код, если расширения невозможно опубликовать под GPL, то здесь возвращаешь университету то, что можешь. В общем, вариация BSD лицензии.

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

Тем более, схемы, написанные на CL, обычно не имеют полноценных continuations

Даже пример из PAIP: http://www.norvig.com/paip/compile3.lisp (400 строк) — и то умеет call/cc .

либо являются интерпретаторами

Как правило компилируются в байткод.

реализовать с помощью CPS идею сохранения и восстановления стека.

Тогда нам всё равно нужен defun/cc и call/cc. В screamer не могу аналогов найти...

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

И даже SBCL-ский степпер позволяет походить по коду после break.

А в arnesi для (defun f0 ... (break) ...) (defun/cc f1 ...) не даёт?

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

Всю голову уж сломал об эту тему. Проблема в том, что расползается постановка задачи, захотелось легковесных тредов «вообще», а не конкретно то, что нужно для данной задачи. И вторая, практическая сторона вопроса, что хочется надёжной реализации, а не той, которую ещё год допиливать.

Как правило компилируются в байткод.

Если в байткод - то да. Я имею в виду, что если схема именно транслируется в лисп, то там не будет настоящего call/cc.

Тогда нам всё равно нужен defun/cc и call/cc. В screamer не могу аналогов найти...

either во внутренней функции и all-values во внешней позволяют зайти в функцию один раз и вернуться из неё несколько раз. Т.е. это своего рода continuations. Но всё же тут пока нет возможности скопировать состояние потока - нельзя выдрать из него состояние стека. Похоже, что это всё же не совсем то, что надо, а может, я просто не догнал, как это реализовать. Ща ещё помучаюсь.

И даже SBCL-ский степпер позволяет походить по коду после break.

А в arnesi для (defun f0 ... (break) ...) (defun/cc f1 ...) не даёт?

Не пробовал, но предпосылок нет - это интерпретатор.

В общем, похоже, остаётся два пути: либо допиливать arnesi (править в нём баги) и пережить отсутствие отладчика, либо лезть в недра SBCL и научиться «честно» копировать состояние процесса. Вряд ли я готов опускаться на уровень С, но можно попробовать компилировать лисп в лисп же, где сделать свой стек вместо настоящего стека.

Попробовал cl/cont. Похоже, что оно хуже ходит, чем screamer.

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

Вот как я сделал call/cc на базе скримера. Хотя пока не на 100% уверен в жизнеспособности. Но если это получится, это будет большая победа, потому что поддерживается отладчик и это всё же нативный код (хоть и после CPS).

С другой стороны, кроме call/cc, нужно ещё уметь сохранять/восстанавливать env, а это отдельная работа.

Ща попробую это сделать.

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

В общем, скример меня тоже не устроил, потому что он не поддерживает толком flet, labels и macrolet.

Arnesi тоже не внушает доверия.

Я взял интерпретатор из SBCL и переделываю его на некую виртуальную машину. Код здесь: https://bitbucket.org/budden/yar/src/default/fb2/call-cc/my-full-eval.asd?at=...

Я на 99,9% уверен, что данный мини-проект завершится успешно. К сожалению, не получится компиляция, а будет только интерпретация. Ну и ладно.

Я называю его «мини», потому что мне нужно по простым формальным правилам переработать порядка 700 строк.

den73 ★★★★★
() автор топика
Последнее исправление: den73 (всего исправлений: 1)
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.