LINUX.ORG.RU

Lisp: с чего начать?


3

5

В институте узнал про язык программирования Lisp. До этого писал только на Паскале и C. Оказывается, там весьма много диалектов: ISLISP, Common Lisp (как я понял, эти 2 устаревшие), Scheme + новые, такие как Clojure, newLisp, Arc. Какой мне выбрать для написания десктопных приложений (я бы хотел сделать свой инструмент для Computer Aided Translation, что-то сравнительно простое на gtk)? Хотелось бы так, чтобы надо было несильно переучиваться, что-то похожее на Pascal.

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

На lisp-lor-faq прочитал:

В самом деле зачем? Это же «архаичный, академический язык», на нём «никто не программирует», «он не востребован среди работодателей.» Эти и подобные им высказывания, нередко можно услышать от людей вовсе незнакомых с lisp или в лучшем случае, когда-то немного слышавшими о нём в институте, от чего у них осталось лишь впечатление языка с огромным количеством скобок.

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

И ещё:

хотя есть конечно области, где Lisp применять было бы неразумно, например, для реализации вычислительных методов.

Можно узнать почему?

vonenij ()

Имхо с Clojure — вменяемое количество синтаксического сахара и библиотек.

PolarFox ★★★★★ ()

Английская википедия говорит о 4 доживших до современности: Scheme, Common Lisp (хотя старый, но, оказывается, живой), ISLISP, Clojure (самый молодой).

Про ISLISP что-то мало что гуглится. Оно живое?

vonenij ()

Дата регистрации: 07.01.2014 23:03:52

Ну толсто же.

encyrtid ★★★★★ ()

«Мир лиспа». Можно только первй том. Если не зацепит, то оно тебе ненужно. Живи в своём болоте.

ziemin ★★ ()

Ну если ты в лиспе ещё ничего не понимаешь, то я в своё время читал «Practical Common Lisp» - ничего так. Есть и перевод на русский.

Если понравится, то дальше сам разберёшься, скорее всего. Ну или будешь знать, что спрашивать. Лично я сейчас ракетом балуюсь. Но на серьёзный уровень в лиспе не претендую.

DarkEld3r ★★★★★ ()

Вот раньше Kuka гораздо более лучше набрасывал.

aedeph_ ★★ ()

сейчас начнется холливар... я бы его и сам начал, но моя дама сердца очень тепло относится к лиспу, хотя сейчас прогает на ABAP'е. почему? кормят лучше :)

зы: но про ABAP тоже ничего теплого сказать не могу, он слишком узкоспециализирован и просто не интересен.

ззы: но холливар начнется %)

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

он не более лучше набрасывал, а просто набрасывал. этот же бред распарсить было трудно.

anonymous ()

Lisp: с чего начать?

на первое отлично подойдет борщ

registrant ★★★★★ ()

Кто это сказал, что CL устарел? Бред.

Три живых диалекта - Common Lisp, Scheme и Clojure. Scheme используется в основном в академических целях, кроме реализации Racket, которую в принципе можно назвать отдельным диалектом.

Начинать лучше с CL, наверное. Почитай http://lisper.ru/pcl/ Scheme простая, но непрактичная. Clojure - жабоспецифичная слишком, плюс в ней слишком много кривых приколов типа STM.

lovesan ★☆ ()

Racket - это самый передовой лисп.

Начинай с него.

Плюсы:

  • Отличная IDE - DrRacket, (которая идет сразу в установщике), на первое время хватит (да и на потом, там есть макрстепперы и профилировщики);
  • Есть очень хорошая книга, которая подойдет даже для полных даунов (htdp);
  • Есть мода совместимости с SICP, можно будет копировать примеры прямо из книги;
  • Хорошие библиотеки на все случаи жизни;
  • Живое коммунити (канал #racket на фриноде, где терпеливо ответят на любые нубские вопросы)
  • Заточенность на иммутабельные структуры данных.

Минусы:

  • Тормозная реализация, много специфики при оптимизации;
  • Более сложная макросистема чем в CL;
  • Некоторая академичность, которая встает боком в продакшене (например мало занимаются оптимизацией jit, нет автоинициализаторов полей для структур, зато есть всякие интерфейсы и дженерики для них же)
x4DA ★★★★★ ()
Последнее исправление: x4DA (всего исправлений: 1)

Тем не менее, коммерческие лиспы LispWorks и Allegro CL реализуют именно стандарт Common Lisp, а это о чем-то да говорит.

На русском вышел не так давно перевод книги ANSI Common Lisp. За исключением небольшого ляпа переводчиков в толковании текста относительно оптимизации хвостового вызова (в оригинале там корректно, но не совсем понятно без отсылки к PAIP), русский текст достаточно хорош (почти как переводили в советские времена). Начни с этой книги.

Поставь SBCL, Clozure CL, clisp и LispWorks Personal Edition или бесплатную версию Allegro CL. Последние два самодостаточны, а для первых трех нужны еще emacs и slime.

dave ★★★★★ ()

Я думаю, что тебе лучше не начинать вообще, чтобы не было разочарований. Я серьезно. Откажись от этой идеи начинать работать с Lisp.

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

За исключением небольшого ляпа переводчиков в толковании текста относительно оптимизации хвостового вызова (в оригинале там корректно, но не совсем понятно без отсылки к PAIP), русский текст достаточно хорош (почти как переводили в советские времена).

А можно конкретнее? Я читал перевод, но вроде бы ничего такого не заметил.

Можно ссылкой на страницу.

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

Используй Clojure.

Использовать хипстерский недолисп Clojure сейчас очень модно, молодежно, да.

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

Мне, кстати, там не понравилось, что «stack» перевели как «стопка».

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

Часть 13.2. Английский текст про оптимизацию хвостового вызова корректен, но его можно истолковать неверно, что, кажется, и произошло в русском переводе. Есть очень распространенное заблуждение. Многие не понимают простой вещи. Хвостовой вызов действительно можно преобразовать в цикл, как это показано в PAIP, но это не значит, что это должен быть цикл самого языка высокого уровня. Но можно построить абстрактную машину, где любой хвостовой вызов фактически превращается в цикл.

Прямой хвостовой вызов обычно преобразуется в цикл самого языка. Так сделано в Scala и во многих компиляторах Common Lisp. Кажется, даже GCC умеет.

С косвенным хвостовым вызовом все сложнее, когда рекурсивный вызов передается через лямбду. Для F#, например, нужны извраты на уровне виртуальной машины CLR. Но упомянутый мною выше PAIP Питера Норвига показывает, что все могло бы быть гораздо проще, будь другим соглашение о вызовах функций.

Из общелиспов по моим наблюдениям и тестам только SBCL умеет оптимизировать косвенный хвостовой вызов.

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

Lisp: с чего начать?

С Python, Ruby или C++, т.е. с живых, используемые в повседневной работе языков. А потом можно перейти на LISP, типа для гурманов.

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

А потом можно перейти на LISP, типа для гурманов.

Реализаций «LISP» в природе не существует. О чем вообще разговор?

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

Про ISLISP что-то мало что гуглится. Оно живое?

Платная вариация используется как лисп для cad-ов.

antares0 ★★★ ()
Ответ на: Racket - это самый передовой лисп. от x4DA

Тормозная реализация, много специфики при оптимизации;

В целом, на уровне sbcl. Нету режима «ничего не проверять» (safety 0) при котором sbcl работает почти как C++, но на некорректных данных вместо запуска отладчика падает с segfault'ом.

Более сложная макросистема чем в CL;

Она не сложнее, она просто другая.

Можно сравнить:

CL:
(defmacro swap (x y)
  (let ((tmp (gensym))
    `(let ((,tmp ,x))
       (setf ,x ,y)
       (setf ,y ,tmp))))

Racket:
(define-syntax-rule (swap x y)
  (let ([tmp x])
    (set! x y)
    (set! y tmp)))

или

CL:
(defmacro shift-to (from to)
  (assert (= (length from) (length to))
  (let ((tmp (gensym)))
    `(let ((,tmp ,(car from)))
        ,@(mapcar (lambda (x y) `(setf ,x ,y)) 
                  (cdr to)
                  (cdr from))
        `(setq ,(car to) ,tmp))))

Racket:
(define-syntax shift-to
  (syntax-rules ()
    [(shift-to (from0 from ...) (to0 to ...))
     (let ([tmp from0])
       (set! to from) ...
       (set! to0 tmp))]))

monk ★★★★★ ()
Ответ на: комментарий от monk
(defmacro shift-to (from to)
  (assert (= (length from) (length to))
  (let ((tmp (gensym)))
    `(let ((,tmp ,(car from)))
        ,@(mapcar (lambda (x y) `(setf ,x ,y)) 
                  (cdr to)
                  (cdr from))
        `(setq ,(car to) ,tmp))))

Я бы рекомендовал тебе проверять то, что постишь, в REPL'е. Нет, ну не первый раз уже :)

(mapcar (lambda (x y) `(setf ,x ,y))

Особенно этот момент.

А что тут ты задумывал? Типа (shift-to (a b) (b a)) пересылает a в b, b в a?

vonenij ()
Ответ на: Racket - это самый передовой лисп. от x4DA

например мало занимаются оптимизацией jit

С jit'ом там неплохо. А вот некоторые стандартные библиотеки... Например, (match x [(list a b c) (f a b c)]) работает раза в 3 медленнее, чем (let-values ([(a b c) (apply values x)]) (f a b c)).

Аналоги special переменных из CL, которые называются parameters работают в 5-10 раз медленнее, чем обычные переменные (в CL в 2 раза).

нет автоинициализаторов полей для структур,

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

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

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

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

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

Исправленный вариант

(defmacro shift-to (from to)
  (assert (= (length from) (length to)))
  (let ((tmp (gensym)))
    `(let ((,tmp ,(car from)))
        ,@(mapcar (lambda (x y) `(setf ,x ,y)) 
                  (cdr to)
                  (cdr from))
        (setq ,(car to) ,tmp))))
Не закрыл скобку у assert

Что не так с (mapcar (lambda (x y) `(setf ,x ,y)) (cdr to) (cdr from)) ? Оно работает

Типа (shift-to (a b) (b a)) пересылает a в b, b в a

Обобщенный swap. (shift-to (a b c d) (d a b c)) делает то же, что и (psetq a d b a c b d c), но выделяет память на одну временную переменную, а не на 4.

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

Кстати, могу я спросить, каким редактором ты это набирал?

Я предполагаю, что тем же, которым ты набирал этот вопрос :-) В браузере.

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

Что не так с (mapcar (lambda (x y) `(setf ,x ,y)) (cdr to) (cdr from)) ? Оно работает

Пардон, ошибка была тут:

(setq ,(car to) ,tmp)

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

Пардон, ошибка была тут: (setq ,(car to) ,tmp)

Лишний апостроф. Я примерно это и имел в виду, когда говорил, что scheme-вские макросы проще.

Разница в том, что в CL строишь произвольный список, а в scheme отображение между входными и выходными параметрами. Разница где-то как между C и PL/SQL.

monk ★★★★★ ()

так что решили? какой лисп то юзать? или может лучше вообще не лисп а хаскель/ерланг?

x0r ★★★★★ ()
Ответ на: Racket - это самый передовой лисп. от x4DA

Re: Racket - это самый передовой лисп.

До этого писал только на Паскале и C

Racket - это самый передовой лисп. Начинай с него.

Сурово. Утонет нафиг. Лучше уж какой-нибудь маленький (недо-) лиспик поковырять или там схемку в с-код подцепить. Чтоб пронять разницу более чем достаточно.

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

Ну а вот когда приходится ломать гигиену вещи усложняются.

Ну, и не забывай про syntax model. Нужно четко понимать синтаксические контексты.

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

называются parameters

которые а-ля parametrize?

Вот CLOS не хватает

clos или мультметодов/комбинаторов?

нигде в стандартных библиотеках не используется.

а в CL разве CLOS на каждом шагу встречается?

x4DA ★★★★★ ()
Последнее исправление: x4DA (всего исправлений: 1)
Ответ на: Re: Racket - это самый передовой лисп. от anonymous

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

Траль в /0 написал что хочет сделать свой CAT. Недолиспик/голая схемка будет непрактична для такого.

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

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

Я что-то не догнал. Инициализатор позиционный - автоинициализация не нужна. Так чтоли?

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

Haskell у меня не пошел как-то. Дочитал «Real World Haskell» до половины и всё.

какой лисп то юзать?

Про Scheme я пока мало прочитал по сравнению с другими, так что надо сначала познакомиться с ними в равной мере, а потом решить

vonenij ()

Оказывается, там весьма много диалектов: ISLISP, Common Lisp (как я понял, эти 2 устаревшие),

Толсто.

Scheme + новые, такие как Clojure, newLisp, Arc

Не нужно.

Хотелось бы так, чтобы надо было несильно переучиваться, что-то похожее на Pascal.

Супертолсто.

Мне его порекомендовали

У вас там в институте умеют прикалываться.

А если серьезно, то читай PCL, потом SICP, после этого потыкай SBCL и Racket. Полученые знания пригодятся при изучении крестов и бустов.

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

которые а-ля parametrize?

Ну да. http://docs.racket-lang.org/reference/parameters.html Используются они гораздо реже, чем defvar, поэтому не так хорошо оптимизированы.

clos или мультметодов/комбинаторов?

И мультиметодов, и defgeneric отдельно от класса, и MOP...

а в CL разве CLOS на каждом шагу встречается?

Практически да. Возьми любой web, любой доступ к БД. Даже iterate внутри CLOS использует. Сложнее найти, где его нет (кроме alexandria ничего в голову не приходит). CLOS в CL настользо же часто используется, как классы в C++.

В Racket для расширяемого API классы неиспользуются. Расширяемость реализуется не ООП, а модулями (протранство имён) и callback'ами (если надо переопределить часть логики). Единственное место на классах — GUI.

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

Инициализатор позиционный - автоинициализация не нужна. Так чтоли?

Ну да. У тебя в defun тоже автоинициализации нету. Хотя потенциально можно было бы как в Visual Basic: print MyFunc(1,,,,5);

А так немножко есть:

> (struct posn (x y [z #:auto])
    #:auto-value 0
    #:transparent)
> (posn 1 2)
(posn 1 2 0)

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

читай PCL, потом SICP, после этого потыкай SBCL и Racket.

Поддерживаю. Даже если не понравится лисп, узнаешь много полезных методик для других языков.

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

Сложнее найти, где его нет (кроме alexandria ничего в голову не приходит). CLOS в CL настользо же часто используется, как классы в C++.

мне collectors очень нравятся.

ados ★★★★★ ()
Ответ на: Re: Racket - это самый передовой лисп. от anonymous

Racket

Сурово. Утонет нафиг. Лучше уж какой-нибудь маленький (недо-) лиспик поковырять

В Racket есть пачка Teaching languages + книжка для постепенного изучения схемы (Racket) по ним.

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

Не нужно.

Почему? Особенно насчет newLisp интересует. Насчет Closure, я согласен.

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

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

collectors

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

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

мне collectors очень нравятся

Хотя где-то в своих проектах используешь? Для C++ тоже есть библиотеки, где сплошь шаблоны и функции и ни одного класса (вроде даже в boost'е видел). Но непопулярно.

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