LINUX.ORG.RU

Посоветуйте «lisp»

 ,


3

5

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

ЗЫ Капелька бояна http://imgs.xkcd.com/comics/lisp.jpg

Перемещено mono из talks

★★★

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

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

Я очень терпелив, спрошу ещё раз. Как всё это достигается.

Трансляцией в хост язык (Racket). Механизм приблизительно аналогичен работе с readtable в CL, но есть чёткое разграничение на область действия реализуемой таблицы чтения. Также остаются синтаксические свойства схеме (привязка к определению, гигиена, ...). Благодаря этому, DrRacket может делать синтаксический контроль на лету.

Пример реализации http://hashcollision.org/brainfudge/ (если действительно интересно).

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

Собственно, реализация рестартов - строки 499-569. Это чтобы не было воплей о том, что «не так уж просто оно делается бла-бла-бла».

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

Трансляцией в хост язык (Racket). Механизм приблизительно аналогичен работе с readtable в CL

Понятно. Посмотрел по ссылке, ну так е... твою медь. Я то думал, там что-то новое внедрили, а там syntax-rules же. Да и readtable. Ну собственно, а в чем разница с CL? Ну кроме гигиены?

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

Ну это понятно.

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

Да, но насколько я понимаю, в JS все исполняется в один поток.

В racket green threads, они реализованы внутри рантайма и не имеют отношения к системным потокам/процессам.

У green threads могут возникать проблемы общего доступа к ресурсам? Такая проблема может существовать?

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

Я могу услышать конкретный вопрос вида

Ты дурачок, чтоли? Я тебя уже 3 раза спросил: как описывается синтаксис нового языка? Впрочем мне уже ответили, что таки да, на syntax-rules и readtable. Хоть ты и утверждал обратное.

В общем, свободен, не смею задерживать.

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

Ты дурачок, чтоли? Я тебя уже 3 раза спросил: как описывается синтаксис нового языка?

Нет, ты не спрашивал. Во-первых, БНФ (как еще кто-то описывает синтаксис)? Хотя есть и альтернативные подходы - например, пишется только лексер, а парсер делается на syntax-parse (~ атрибутная грамматика).

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

Впрочем мне уже ответили, что таки да, на syntax-rules и readtable.

Нет, syntax-rules не при чем. Я уже устал это повторять.

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

Нет, ты не спрашивал. Во-первых, БНФ

Специально для тебя

Я тебя конкретно спросил про syntax-rules, ты сказал - нет. Что нет? Есть другой способ описания синтаксиса? БНФ может быть? Или что-то ещё?

Выделил тебе, а то вдруг ты слеповат?

По поводу БНФ - в чем тут фишка рэкета, так везде делается. Ну отладчик, это да, интересно. Работает на уровне нового языка, да?

no-such-file ★★★★★
()
Последнее исправление: no-such-file (всего исправлений: 1)
Ответ на: комментарий от phill

У green threads могут возникать проблемы общего доступа к ресурсам?

Они все выполняются в одном потоке. Какого именно рода проблемы?

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

По поводу БНФ - в чем тут фишка рэкета

Ни в чем. При чем тут вообще то, как описывается грамматика? Об этом никто не говорил.

Смысл в том, что благодаря syntax objects искаробки работает то, что в другом случае тебе пришлось бы делать руками. Причем работает вполне корректно.

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

Работает на уровне нового языка, да?

Всмысле?

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

Какого именно рода проблемы?

Ну, взаимная блокировка, наверное.

Вообще, вот что пишется по node:

Синхронные операции хороши своей простотой. Особенно, по сравнению с тредами, где проблема с параллельным доступом к ресурсам так и хочет свести ваш код к состоянию «WTF?!».

В Node.js вам не нужно волноваться о том, что происходит на бэкэнде: достаточно просто использовать коллбеки при работе с I/O. Это даст вам уверенность в том, что ваш код не заблокирует работу сервера. В отличии от использования дополнительных тредов или процессов, это хорошее решение с точки зрения производительности. Асинхронный I/O — это замечательно, потому что операции ввода/вывода гораздо затретнее, чем простое исполнение кода. К тому же, программа должна заниматься более полезными делами, чем постоянно ждать I/O. Событийный цикл — это «сущность которая перехватывает и обрабатывает внешние события и конвертирует их в функции обратного вызова». То есть, вызовы I/O — это определенные точки, в которых node.js может переключаться от одного запроса к другому. При обращении к I/O, ваш код сохраняет коллбек, и возвращает контроль обратно, в среду выполнения node.js. Сохраненный коллбэк будет вызван позднее, когда все необходимые данные будут получены.

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

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

разные области применения. Жаву надо юзать для кода, который основан на мутабельном состоянии и «паттернах проектирования». Лисп нужно юзать на обработке списков, немутабельных данных и особенно - немутабельной многопоточности. Если в проекте есть и то, и другое, можно использовать их одновременно - они не исклчают друг друга, а взаимовыгодно дополняют.

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

Лисп нужно юзать на обработке списков, немутабельных данных

А чем лисп не угодил для обработки кода, который основан на мутабельном состоянии?

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

Да и readtable. Ну собственно, а в чем разница с CL? Ну кроме гигиены?

В стабильности. Я разрабатывал https://github.com/Kalimehtar/advanced-readtable для CL. Пока используешь только в файлах и работаешь пакетно, ещё терпимо. Как только начинаешь работать через SLIME, начинаются пляски: часть символов SLIME переопредееляет сам, часть — юезусловно предполагает поведение по-умолчанию. В REPL либо свой readtable перекрывает стандартный при загрузке всех файлов, либо стандартный readtable не позволяет исолнять команды из файла с переопределённым (синтаксис не совпадает).

В Racket любой синтаксис работает в рамках модуля. REPL также всегда в каком-то модуле. Более того, если я изменю определение синтаксиса или макрос в библиотеке, то все зависимые модули прозрачно перекомпилируются.

Поэтому я последним пунктом и написал, что Racket приучает к более аккуратному программированию. В CL понимаешь, что все виды abuse всё равно перехватить не получится и тупо забиваешь на полную проверку данных. Хороший отладчик также поощряет неряшливость (зачем всё тестировать, если почти из любьой позы поднять можно). В Racket нет прямого доступа к любому символу любого пакета. Для импортированного модуля невозможно изменить то, что явно не разрешено на изменение. Ну и местная культура документации в файлах документации (HTML), а не вперемешку с кодом (для документирования есть целый язык Scribble). Интегрирована подсистема для тестрования (rackunit).

В общем, на CL легко прототипировать, легко отлаживать, но писать что-то более-менее большое и надёжно проще на Racket.

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

Да вроде всем угодил, кроме того что Java - более удобная абстракция.

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

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

Поэтому я последним пунктом и написал, что Racket приучает к более аккуратному программированию. В CL понимаешь, что все виды abuse всё равно перехватить не получится и тупо забиваешь на полную проверку данных. Хороший отладчик также поощряет неряшливость (зачем всё тестировать, если почти из любьой позы поднять можно). В Racket нет прямого доступа к любому символу любого пакета. Для импортированного модуля невозможно изменить то, что явно не разрешено на изменение. Ну и местная культура документации в файлах документации (HTML), а не вперемешку с кодом (для документирования есть целый язык Scribble). Интегрирована подсистема для тестрования (rackunit).

Вероятно, именно это и имеется в виду, когда говорят, что ракет — это не лисп (по духу):)

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

Ну, взаимная блокировка, наверное.

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

достаточно просто использовать коллбеки при работе с I/O.

Это тоже есть: http://docs.racket-lang.org/reference/futures.html — причём здесь реальная параллельность когда возможно

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

ракет — это не лисп (по духу)

ракет — это scheme (по духу). Там значально был уклон в сторону чётких API, компиляции, документирования в стиле «научная статья на тему ...». Есть сомнения насчёт правомочности узурпации Common Lisp'ом термина «лисп».

В остальном — согласен полностью. Идеология «программу не проектирую, программу выращивают» — это строго CL'евское. В эту же группу попадает Smalltalk и Genera Lisp.

А Scheme скорее родственник Haskell'у с его идеологией «если скомпилировалось, то, как минимум, падать не должно».

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

программу не проектирую, программу выращивают

По этому поводу, есть очень интересное эссэ Ричарда П. Гэбриела Worse Is Better, анализирующая различие подходов к разработке.

русская вика:http://ru.wikipedia.org/wiki/Чем_хуже,_тем_лучше

английская: http://en.wikipedia.org/wiki/Worse_is_better

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

Ну, взаимная блокировка, наверное.

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

Что-то, это не похоже на нити. Насколько я понял, все реализовано на уровне языка, и програмист может абстрагироваться от тредов

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

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

Ну делай при помощи шаблонизаторов, они тоже есть. Смысл того примера именно в минималистичности и простоте.

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

эссэ Ричарда П. Гэбриела Worse Is Better

Спасибо, ушёл читать.

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

2. Нормальные модули.

Они разве не завязаны на файлы. Что как-то сразу делают их «номальность» на любителя.

5. racket/gui с единым стабильно работающим интерфейсом для X11/Win/Mac.

Используя Tk получаешь примерно такую же стабильную и не всегда нативную хрень но под все платофрмы.

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

А named-readtable не вариант? Я понимаю еще хвалить racket за возможность описания синтаксиса/граматики, но readtable?

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

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

Ну вообще можно, гейзер-то делает.

> (require racket/enter)
> (compile-enforce-module-constants #f)
> (module test racket
    (provide print-x)
    (define x 1)
    (define (print-x)
      (displayln x)))
> (require 'test)
> x
x: undefined;
 cannot reference an identifier before its definition
> (print-x)
1
> (enter! 'test)
> x
1
> (define x 2)
> x
2
> (enter! #f)
> x
x: undefined;
 cannot reference an identifier before its definition
> (print-x)
2
> 

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

Есть сомнения насчёт правомочности узурпации Common Lisp'ом термина «лисп»

Есть сомнения насчет правомочности scheme называться лиспом. Кроме синтаксиса в ней ничего от лиспа не было, и она, к сожалению, оказала влияние и на CL (что неудивительно, ибо горе-(co-)дизайнер scheme Гай Стилл занимался и разработкой CL). Изначально, лиспы были грязными языками, и очень мощными, динамическими, анти-алгол-стайл, короче, а схема — это алгол.

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

Смысл в том, что в racket за этим вообще следить не надо, т.к. reader принадлежит порту (у «лишп-машины» в общем ридера как бы нет). А т.к. любой файл - это порт, то любому файлу.

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

Все функции Racket

Всмысле примитивы.

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

В общем, вся асинхронность (cl-async, cl-futures, weblocks, ...) в CL работает через костыль cl-cont.
cl-async

На сишном libevent

cl-futures

Просто нет

Хотя бы немножко изучи то на что ссылаешся.

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

Они разве не завязаны на файлы. Что как-то сразу делают их «номальность» на любителя.

Нет, модуль - это top-level выражение вида (module module-name language name code ...). С-но файлы модули и представляют (после обработки ридером) именно такой секспр. Никто не запрещает определять модули в репле. По нескольку модулей в файле тоже можно - но это не поощряется.

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

Изучение лиспа полезно само по себе.

Сейчас прибежит Анонимус и скажет, что кроме изучения он ни для чего и не полезен. Или уже сказал?

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

cl-cont

Не называйте ЭТО продолжениями, пожалуйста.

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

Что такого есть в Clojure, чего нет в обычном нормальном лиспе?

Могу сказать, что есть в обычном нормальном CL, но нет в Clojure...

Так, ТС, признавайся зачем ты сделал топик срача между диалектами лиспа? Лучше возьми и попробуй все, они не так сильно различаются, чтобы пришлось тратить много времени на освоение каждого с нуля. У меня был Scheme -> CL -> Clojure. Больше всех понравился и по сей день используется CL, но почему именно уже не очень хорошо помню.

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

Так, ТС, признавайся зачем ты сделал топик срача между диалектами лиспа?

Я не хотел, просто их так много и все так «похожи», если не смотреть вглубь (куда я посмотреть тупо не могу пока) ))))

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

Они разве не завязаны на файлы.

Не совсем. Модуль <= файл. Модуль можно сделать через (module name ...). И наоборот, если единый интерфейс собран из нескольких файлов, то делается достаточно тривиально.

В CL всё равно приходится явно указывать зависимости между файлами. Только вручную в .asd и нет контроля зависимостей, используемых из пакетов.

такую же стабильную и не всегда нативную хрень

racket/gui как раз везде нативен. WinAPI/GTK/не-помню-что-на-MacOS

А named-readtable не вариант?

Его и использовал. Потом пришёл к выводу, что использовать более одной readtable в проекте адски усложняет отладку. Как я уже говорил: проблема в REPL и в том, что asdf наследует readtable из REPL. В случае SLIME дополнительное развлечение с C-c C-c (компиляция отдельной функции).

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

По нескольку модулей в файле тоже можно - но это не поощряется.

Два исключения

(module main ...) --- для top-level форм, которые нужны в самом модуле в REPL, но не нужны, если его использовать как библиотеку

(module+ test ...) — тесты.

Поэтому по несколько модулей в файле почти всегда. Но они «субмодули». Подчинённые основному.

monk ★★★★★
()

бери ракет - самый продвинутый язык из лисп семейства.

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

Поэтому по несколько модулей в файле почти всегда. Но они «субмодули».

Да, про субмодули забыл. Ну, они как раз так спроектированы, чтобы быть по нескольку в одном файле, так что тут все ок. Кстати, модули можно еще через local-require импортировать внутрm лексического контекста - внутри (let (...) ...), например.

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

cl-async

На сишном libevent

Упс, перепутал с https://github.com/deliciousrobots/green-threads

cl-futures

Просто нет

https://github.com/deliciousrobots/cl-future

Хотя бы немножко изучи то на что ссылаешся.

Ну пусть будет ещё https://github.com/AccelerationNet/generators

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

Зато поддерживает рестарты. Я в курсе, что продолжения - это более общий подход. Ок, где можно почитать про методологию применения продолжений, так, чтобы то же нельзя было бы сделать через рестарты? Насколько широка такая область применений?

Аноним поднял интересную тему. Область применения: почти все, где уместны монады (например, асинхронные вычисления). Просто продолжения и монады очень сильно связаны между собой. По сути, второй аргумент функции bind - это продолжение вычисления, а через один из видов продолжений можно выразить монадическое вычисление.

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

По этому поводу, есть очень интересное эссэ Ричарда П. Гэбриела Worse Is Better,

Очень хорошая иллюстрация. Worse is better — нынешний CL, MIT — Racket.

Вот только в эссе не учтена одна вещь: системы развиваются экспоненциально. А плохие системы начинают разваливаться от противоречий. Поэтому живой UNIX — старый UNIX (FreeBSD), а любая попытка сделать нормальное удобное решение (чтобы suspend работал как ожидается, флэшка виделась, принтер подключался, монитор настраивался, ...) приводит к тому, что либо соответсвующий функционал размазан на дюжину пакетов (kernel + пара демонов + Gnome + KDE + ...) либо рождается systemd, который заменяет половину базовой системы.

В CL ровно та же проблема: в любой более-менее крупной системе разработчикам приходится причесать код для единообразия и уменьшения количества «странных ошибок» (когда изменения в одном месте ломают всё в совсем другом). Теперь у нас есть фреймворк hu.dwim.*, нестыкующиеся cl-containers и https://github.com/fare/lisp-interface-library, cffi и uffi, 100500 пакетов с «утилитами», сотни попыток сделать «стандартную библиотеку Common Lisp»... Около 10 интерфейсов к GTK и полдюжины надстроек над CLOS.

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

Что такого есть в Clojure, чего нет в обычном нормальном лиспе?

синтаксис, неизменяемые типы данных, ленивые функции, STM

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