Вот некоторые примеры использования:
(defpackage myapp
(:use :cl21))
(in-package :myapp);;
(defvar *hash* (make-hash-table))(getf *hash* :name)
(setf (getf *hash* :name) "Eitarow Fukamachi")
(setf (getf *hash* :living) "Japan");=> "Japan"
(getf *hash* :name)
(coerce *hash* 'plist)
(defparameter *vector*
(make-array 0 :adjustable t :fill-pointer 0))(push 1 *vector*)
(nth 0 *vector*);=> 1
(push 3 *vector*)
(nth 1 *vector*);=> 3
(pop *vector*)
(pop *vector*);=> 1
(collecting
(doeach (x '("al" "bob" "joe"))
(when (> (length x) 2)
(collect x))))
Остальное в https://github.com/fukamachi/cl21/blob/master/README.markdown
> Кому там хотелось лисп для 21 века?
Мне. Общий подход верен (новый пакет на замену :cl), но начинка не впечатляет. Думаю, должно быть несколько попыток от разных людей, что бы в итоге получилось хорошо.
Совсем НЕ ради холивара! Говорят, что Clojure как раз лисп для наших дней. Вы с ними не согласны?
> Говорят, что Clojure как раз лисп для наших дней
В интернетах много чего говорят.
Ну хз зачем нужно в таком виде. Лучше бы:
1. Делали все улучшения в отдельных пакетах-проектах.
2. Четко описывали апи пакета такой-то версии (всё же типа замена стандарту, а не просто либа).
3. Соответственно для всего этого свои доки-гиперспеки.
4. Коллекции с расширяемым апи, чтобы можно было один мап юзать и существующие макросы для своего типа. Или делать своё на замену стандартным, сохраняя только интерфейс. В этом лисп не очень, почти все в CL под каждую структуру свое.
5. Многопоточность в коллекциях и вообще бы стандартные коллекции переделать. Например, тут определенная как generic equal явно при новом методе сама хэш функцию не создаст и может сломать hashtable, для которого equal просто символ, выбирающий хэш функцию из стандартных для данной реализации.
Ну, и многих наверное наберется ещё вагон и маленькая тележка таких же пожеланий, без единого патча в проект.
> 1. Делали все улучшения в отдельных пакетах-проектах.
Так теряется весь смысл. Мало ли хороших библиотек, о которых может быть никто и не слышал. Если предельно устаревший пакет :common-lisp, который почти автоматически подключается в каждый пакет. Никто не будет юзать 10 дополнительных хороших библиотек, если есть аналогичные, пусть и кривые, решения в одном стандартном пакете.
> 2. Четко описывали апи пакета такой-то версии (всё же типа замена стандарту, а не просто либа).
> 3. Соответственно для всего этого свои доки-гиперспеки.
На это нужны ресурсы и мотивация. Удобно советовать как делать "правильно", но это очень тяжело и не понятно зачем нужно при активном сообществе в 100 человек.
> 4. Коллекции с расширяемым апи, чтобы можно было один мап юзать и существующие макросы для своего типа.
Что имеется ввиду? Так есть раздел Redefined as Generic functions, что и есть правильное решение. Ну его нужно расширять и наверное делать другим. Но общий подход верный.
> Ну, и многих наверное наберется ещё вагон и маленькая тележка таких же пожеланий, без единого патча в проект.
Ну это очень просто, на Github легко завести свой аккаунт и создать новый проект. Конкуренция библиотек на замену стандартной - это было бы круто.
Не хочу сильно холиварить. Конкуренция - это хорошо, но в опенсорсе лучше чтобы не было сильного перекрывания функционала. Поэтому разбивка на пакеты и будет хороша, делая порог вхождения для конкуренции около нулевым без наличия каких-либо ресурсов. И в отличии от разрозненных библиотек, все кто захочет контрибутить будут оглядываться на уже включённые вещи и принятые подходы. Плюс отдельные пакеты удобнее для цикла разработки, для совместимости и документации. Структура всего проекта при таком подходе будет более ясной и максимально ортогональной. Кому нужно - будет использовать что-то сырое, что могут сломать в дальнейшем или даже выкинуть. Кто-то будет ждать стабильную версию. А релиз - это просто сборник стабильных и лучших (для проекта) пакетов (в общем изначальный проект вроде как и следует похожей идеологии). Ну и один человек явно не сделает лучше замену CL, больше шансов при нормальной организации и вовлечении большого числа участников. Да и деньги явно будет проще привлечь в крупный проект (хотя тоже немного утопично выглядит), а не делать всё исключительно фор фан одному без ресурсов.
>Так есть раздел Redefined as Generic functions, что и есть правильное решение. Ну его нужно расширять и наверное делать другим. Но общий подход верный.
Главное чтобы дизайн интерфейсов был изначально более-менее нормальный, а не ломался постоянно.
Проблема в том, что в 2014 году мы всё ещё не имеем замены для пакета :cl, а сам :cl очевидно не соответствует требованиям времени. В конце-концов кто-то это должен взять и сделать. Если будут пытаться несколько людей, то шансов на успех больше. Удачная замена :cl даёт шанс на "виток энтузиазма" и выход за пределы текущего болота и появления инфраструктуры более высокого уровня.
> Главное чтобы дизайн интерфейсов был изначально более-менее нормальный, а не ломался постоянно.
Как этого достичь? Поиск хорошего решения требует времени и экспериментов. Постоянная поломка не существенна, пока речь идёт о 100 пользователях (а на самом деле их даже столько не будет).
>Проблема в том, что в 2014 году мы всё ещё не имеем замены для пакета
:cl, а сам :cl очевидно не соответствует требованиям времени.
Не знаю, но это вроде не проблема. Тот же js используют и ничего.
>Удачная замена :cl даёт шанс на "виток энтузиазма" и выход за пределы
текущего болота и появления инфраструктуры более высокого уровня.
По мне, так для узкой технологии нужна просто удалённая работа. Это более эффективный мотивитор, нежели "энтузиазм".
То есть проблема не в лиспе, а в бизнес-процессах. Без них хоть в десять раз лучше сделай - ничего не выйдет.
>Постоянная поломка не существенна, пока речь идёт о 100 пользователях
100 проектов это весьма неплохо для либы. Во время альфы можно ломать, но вот релиз уже нужно делать совместимость, особенно учитывая оценку в 100 проектов.
Типа компьютеры уже стали слишком быстрыми и можно заменить быстрые нормальные функции тормозными родовыми?
> Типа компьютеры уже стали слишком быстрыми и можно заменить быстрые нормальные функции тормозными родовыми?
Да, для многих задач больше не нужен C.
> заменить быстрые нормальные функции тормозными родовыми?
Ну это могло бы начаться как design-phase, так что пофиг на скорость. А потом, можно было бы над оптимизацией задуматься в конкретных реализациях CL.
Хотя по мне, мне и так CL нравится -- такой как есть, было бы больше хороших библиотек. А если пилить новый лисп, то это уже будет не CL. Clojure -- уныла и на новый лисп никак не тянет.
LFE и то интереснее, хотя бы на крутой Erlang/OTP платформе работает и тоже lisp-2.
Вот именно, побольше библиотек!
> Вот именно, побольше библиотек!
Что бы было больше библиотек, надо увеличивать численность активного сообщества. Но как это сделать? Неадекватность стандартной библиотеки это одна из та вещей, которая отпугивает от CL.
А в чем неадекватность стандартной библиотеки проявляется?
Думаю, что библиотека стандартная хоть и кривовата, но неадекватной её назвать нельзя.
Самое страшное, на мой взгляд - это документация по стандарту.
Всё набрано разными шрифтами, из-за этого текст тяжело читать.
Куча лишних и отвлекающих внимание гиперссылок на тривиальные вещи.
Уродливый глоссарий, где не попадаешь сразу на нужную статью.
Конкретный пример:
http://www.lispworks.com/documentation/HyperSpec/Body/f_find_.htm
Зачем слова nil, function, generalized boolean, designator, element выделены гиперссылкой при
каждом их появлении? Это полный маразм.
Где перекрёстные ссылки на member и search?
Большой дефицит перекрёстных ссылок наблюдается везде в документации.
Предлагаю всем скинуться и нанять лампового веб-дизайнера, который все сделает мягко и красиво. Тогда наверно и домохозяйки потянутся в мир лиспа
Сколько это может стоить?
А вообще, надо провести опрос среди неосиляторов - что именно их сломало.
Я вот пытался сделать подобный опрос про лиспворкс конкретно, но можно обобщить.
Да известно же, 90% скажут "Скобочки, кругом одни скобочки! о_О". Это как плеваться на отступы в питоне. Мне кажется, причина в основном, как уже выше было подмечено, сообщества, библиотек и... может сделать в либе какие-то вещи более удобней. Например вместо (gethash 'one-entry *my-hash*) писать (*my-hash* 'one-entry). Как в том же Clojure, мелочь, но приятно. Но на что лично я наткнулся, так это на отсутствие большого количества форумов с какими-то схожими проблемами. Даже сложилось впечатление, что люди которые пишут на лисп - боги, у которых не бывает никаких проблем вообще. Причем вопросы довольно тривиальные, просто недостаточно знаний, а ответов не находил. Правда это наверно порождает низкоуровневых программистов, которые просто копипастят код не задумываясь. Но тем не менее мне это показалось проблемой.
> Сколько это может стоить?
Есть варианты. Например, редизайн cliki.net обошёлся бесплатно. Можно посмотреть примерные расценки на каком-нибудь сайте фрилансеров.
>Большой дефицит перекрёстных ссылок наблюдается везде в документации.
Там можно нажать стрелку вверх и вылезет вся глава по подобным функциям. По мне, так документация близка к идеальной.
Вообще, это офф, конечно, но я всё же приведу свой список, того, что досаждает.
1. Поиск ошибки. В некоторых случаях (в лиспворксе) место ошибки можно найти только совсем извратными методами типа метода половинного деления.
Простейший способ устроить засаду - написать топ-левел форму, которая компилируется, но вызывает ошибку в load-time. Т.е.., написать в файле
(/ (read-from-string "0")). При этом, теоретически, исходник известен и нет причины, чтобы его не показать мне.
2. То же касается ошибок чтения, например, когда в тексте есть лишняя запятая. Тут я долго трудился и сделал специальный инструмент, который позволяет находить ошибку
за одно нажатие кнопки (в лиспворксе). В целом же это задача непростая.
3. То же касается несбалансировнных скобок. Вроде и есть команда find unbalanced parens, но она какая-то странная.
4. Ридмакросы - нарушают масштабируемость по количетсву подключаемых библиотек. Решил для себя введением symbol-readmacro, но это непереносимо.
5. uppercase идентификаторы. Текст, набранный капслоком, неудобочитаем, и трудно делать интерфейсы с тем же С без постоянного использования.
Проблема не имеет красивого решения в существующей экосистеме библиотек. Для себя я сделал так, чтобы CamelCase идентификаторы
оставались в том же регистре, как есть, но это регулярно вызывает проблемы.
6. Итерация. Есть iterate, но в лиспворксе он не дружит со степеером. Значит, нужны простые циклы, типа как в С. Есть, конечно, do, но его синтаксис
содержит больше скобок, чем я могу воспринять, поэтому я им никогда не пользуюсь. Мне (и ещё менее продвинутым домохозяйкам) нужен простой цикл
for i from 1 to 10, с оператором continue.
7. Собственно степпер по нативному коду тоже кажется естественным в XXI веке, он, безусловно, возможен, но не знаю, в какой реализации он есть.
Без всяких там перекомпиляций и прочих ужимок должно всё работать, если код скомпилирован с высоким debug.
8. asdf. Полное дерьмо. Хотя мне объясняли, что я просто не умею им пользоваться. Но вот make я осилил за полдня без всякого напряжения извилин,
а тут никак не могу научиться пользоваться за годы. Т.е., пользуюсь, но всё плююсь. Как минимум, нужна команда "открыть файл, в котором найдена ошибка, на редактирование". Я для
лиспворкса такую команду сделал, но это только для лиспворкса. Может, в SLIME такая уже есть.
9. Навигация по исходному тексту. В дельфи, к примеру, я могу за один клик перейти на любую функцию. От декларации за одно нажатие могу перейти к реализации
и обратно. В лиспе это сделать нельзя. Я эту проблему тоже решил, но время на это потратил.
10. Completion имени пакета, т.е. complete-package-name. В SLIME, наверное, до сих пор такого нет. Я сделал, но время потратил.
11. Типизированные глобальные переменные, которые нельзя сбиндить или присвоить значением неверного типа. Хотя, может, я просто не знаю, как это делается.
12. Удобный доступ к полям структур по типу C, т.е. a.b. Есть обходные пути, один из них я освоил и использую, но это кривовато, разработка заняла много времени.
13. Модифицируемые структуры. Структуры очень хороши тем, что они просты и по умолчанию поддерживаются read/print для них есть функция print, способная печатать/читать кольцевые графы. И структуры очень лаконично определяются.
Для объектов этого нет, и, видимо, сделать нельзя (или я не догоняю, как сделать). Но структуры нельзя переопределять без потери данных, как объекты. Нужно бы сделать какой-то
гибрид между ними, который можно читать/печатать, и который может переопределяться.
14. EMACS - отдельная песня.
Все эти проблемы - вроде бы мелкие, но каждая из них на какую-то величину снижает производительность труда. Когда сумма становится слишком велика,
то начинается поражение в конкурентной борьбе.
Ладно, пора работать.
>Но на что лично я наткнулся, так это на отсутствие большого количества форумов с какими-то схожими проблемами.
Это заслуга гиперспеки.
Вот нажми на find кнопочку вверх и убедись, что функции member в этой главе нет,
потому что она находится в главе conses.
remove-duplicates не ссылается на множества, хотя это родственные вещи.
Находясь в read, не так легко перейти к описанию стандартного синтаксиса, и
вообще неясно, как найти способ создать поток. По поводу потока - канонический
пример безполезности глоссария. Из read можно ткнуться в слово stream, попадаешь в глоссарий,
но из глоссария нет ссылки ни на что полезное - ни на оглавление, ни на описание класса stream,
ни на функцию open. Т.е., иди опять в оглавление. Это мелочь, конечно, но обычно,
когда я лезу в доку, у меня в голове уже полный стек, занятый прикладной проблемой.
А стек в голове (моей) имеет ограниченный объём, поэтому я хотел бы не разгадывать
головоломку каждый раз, когда надо что-то найти в документации.
Если бы я не работал с другими продуктами, в которых see also - реально полезная вещь,
я может, и счёл бы эту ситуацию нормой. Но я с такими продуктами работал.
Возможно, удобство или неудобство такой доки зависит от стратегии укладывания знаний
в голове. Для моей стратегии это неудобно, и я не думаю, что я один такой.
>Вот нажми на find кнопочку вверх и убедись, что функции member в этой главе нет,
потому что она находится в главе conses.
Я тут согласен с гиперспекой. Последовательности и консы в разных главах должны быть. Хотя да, само название функции member немного путает.
>Если бы я не работал с другими продуктами, в которых see also - реально полезная вещь,
Ну, вообще скажу в защиту гиперспеки, что во многих случаях там в глоссарии есть отсылка на главу.
Ну или более обобщенно, совершенствовать, как стандарт, так и доки можно бесконечно (да и нужно наверное это делать). Но я считаю, что это не сильно что-то реально улучшит.
>Ну или более обобщенно, совершенствовать, как стандарт, так и доки можно бесконечно (да и нужно наверное это делать). Но я считаю, что это не сильно что-то реально улучшит.
Ну, может быть. Я думаю, пока люди не станут на лиспе делать деньги, ниче не изменится. а не станут, потому что слабое сообщество, как мне кажется. Например у меня был вариант как-то раз сделать сайтик, я долго мучался и боялся выбирать лисп просто потому что его нужно будет поддерживать и улучшать или как-то расширять со временем и не был уверен, что найду подходящие библиотеки под свои нужды. В итоге выбрал лисп, но сайтик не доделал =) Но это уже вина не лиспа, а моя.
Никто не заставляет их быть в одной и той же главе, но что мешает сделать
гиперссылку see also для функций, с похожим функционалом, которые во многих
случаях взаимозаменяемы?
К сожалению, сейчас, видимо, у меня не та ситуация, чтобы раскошелиться на причёсывание
гиперспека или заняться этим. Это всего лишь одна из досаждающих помех, но не более того.
Если бы мне назвали ценник и кто-то бы это организовал - я бы подумал. Но не более того.
Есть и более приоритетные вещи, на которые я бы хотел раскошелиться, но и то не получается.
Так что пусть всё остаётся как есть :)
Я вот думаю, а долго ли cl способен поддерживать современную форму с помощью (defpackage ... (:use :cl-of-new-age... . На какую широту возможностей гибкость такого расширения этого позволяет. Если позволяет в наше время, конечно...
Я вот не очень в этом понимаю, но вот слышал, что вроде в стандарте подложена свинья против продолжений и yield-ов. С другой стороны стандарт неплохо абстрагировался и это позволяет многим современным плюшкам остаться на совести имплементаций.
yield(конкретнее - итераторы) делаются элементарно замыканиями, полноценные же продолжения не нужны и даже опасны
>yield(конкретнее - итераторы) делаются элементарно замыканиями
Нет, не делаются.
>yield(конкретнее - итераторы) делаются элементарно замыканиями
замыкание - это и есть объект в общем-то. насколько я понимаю, yield же делает продолжение, то есть автоматом сохраняет как состояние, так и поток выполнения в любой точке, что в cl нельзя сделать легко из-за тех же блоков с локальными метками. в этом и суть yield - одно слово и всё готово.
А вот где и зачем применяются эти продолжения? У меня вот только угадывается что-то из области асинхронщины, многопоточностей и всякой другой событейщины.
кому не нравится hyperspec, есть:
http://clqr.boundp.org/в C# yield - в compile-time трансформируется в объект и замыкание.Что мешает в CL так же сделать?
http://blogs.msdn.com/b/oldnewthing/archive/2008/08/12/8849519.aspx
Для этого не нужны полноценные продолжения, т.е. кактусовый стек и т.п.
>Что мешает в CL так же сделать?
Явных препятствий для этого нет. Но это - достаточно сложное преобразование кода, я бы не назвал его элементарным.
Если речь идёт о continuation passing style transformation, то оно реализовано в screamer для большого подмножества управляющих конструкций.
За буклет спасибо, но пожалуй, из этих двух я всё же выберу hyperspec.
Теперь у проекта появился сайт:
http://cl21.org/открыл сай проекта, первый пример с заменой format на princ? какой нахрен princ? закрыл, мне такого говна не надо
А format с демоническим синтаксисом в духе регэкспов, нужен?
> А вот где и зачем применяются эти продолжения?
Например, есть у тебя map (mapc, maptree, ..). Надо сравнить две коллекции. С продолжениями я могу выбирать по одному элементу, сравнивать, выбирать следующий. Без них --только копировать всё целиком в список (два).
Или надо написать логику с ветвлением на HTML/Gtk/... без модальных окон. Без продолжений пишется, но получается лапша (много мелких функций onButton).
Или при обработке ошибки выбрать рестарт, посмотреть, что получится, а если не понравилось выбрать другой рестарт.
> Без продолжений пишется, но получается лапша (много мелких функций onButton).
Очевидно, зависит от того, как писать. В CL это может быть неприятно исключительно из-за синтаксиса, а в том же JavaScript обычно можно получить очень даже приличный код.
http://ryepup.unwashedmeme.com/blog/2010/11/21/coroutines-in-common-lisp/
> http://ryepup.unwashedmeme.com/blog/2010/11/21/coroutines-in-common-lisp/
Угу. Thread. Ещё cl-cont есть. Продолжений может быть много. Стоимость встроенного (не cl-cont) продолжения почти такая же, как у замыкания. Потоков больше, чем пару десятков одновременно не запустишь, а на продолжениях можно программы с Erlang'а 1-в-1 переписывать.