LINUX.ORG.RU

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


3

5

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

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

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

Особенно насчет newLisp интересует

Кому-то он не нравился из-за отсутствия GC. Мне он казался маленькой хорошей штучкой. Но потом я узнал про tisl

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

и хитро использует замыкания

Это не хитро. Хитро — книжка Let over lambda. Причём, эти ребята тоже CLOS не любят.

(setf (symbol-function 'pantest)
    (pandoriclet ((acc 0))
      (lambda (n) (incf acc n))))

* (pantest 3)

3
* (pantest 5)

8

* (pantest :pandoric-get 'acc)

8

* (pantest :pandoric-set 'acc 100)

100
* (pantest 3)

103

.... вот такой ООП

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

Особенно насчет newLisp интересует

Там же нет лексической видимости, а значит только костыльные замыкания и магия. Добро пожаловать в 60-тые.

Ну и арк, это ж вроде как, от признанного авторитета

Академическая игрушка для чесания ЧСВ признанного авторитета.

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

Это не альтернатива. Это они открыто пишут про отсутствие GC и выставляют это каким-то своим достижением.

В общем, мне оно нравится только из-за малого веса

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

Там же нет лексической видимости, а значит только костыльные замыкания и магия. Добро пожаловать в 60-тые.

Нет по дефолту, но это ж интерпретируемый язык, ЕМНИП, там просто другая идеология. Автор считает как раз, что компиляция - зло. То же самое, по-моему, в picolisp. На хабре есть статья , в которой автор отстаивает преимущества интерпретации. Я пока не знаю, кому верить. Маленько трогаю их лиспы, посмотрим, что там дальше получиться.

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

Автор считает как раз, что компиляция - зло.

Ну так он, как бы, дебил. А дебилам свойственно дебильничать.

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

Статья написана без знания дела. Например мерить скорость, сравнимая с Clisp как с некоей эталонной реализацией CL, это намерено давать своей реализации фору

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

К тому же он пишет про какие-то «узлы», написанные на C, хотя тот же SBCL написан на Common Lisp. + Много идиотизма

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

Я как-то читал, что Алан Кей придерживается похожей точки зрения. И очень был недоволен новыми лиспами. В списке рекомендованной им литературы, отсылка к lisp-1.5 user manual. Так что для меня неочевидно пока как-то, кто из них прав, рановата пока еще судить, не настаиваю.

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

Щас нет уже вроде, если будешь паинькой, не буду. Для обучения диалог важней личных счетов. но тока продуктивный.

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

Ещё перл оттуда:

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

Я скачал и установил. И что?

: (* 10.5 2) -> 22

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

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

Да. Просто так. Решили прибить и прибили. А я им за это LNSP тредов

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

Вот анекдот, кстати: пошел я регистрироваться заново и временное мыло сгенерировало мне вариант: wonenij@blah-blah.com. Но что-то пошло не так и пришлось регистрироваться как vonenij. Но зато как символично: Вонений!

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

Для меня это темный лес, но я думаю, не всегда нужно много типов, это ведь от задачи, зато в простоте выигрыш. Он это обосновывает вроде:

The reasons for this design decision are manifold. Floating point numbers smack of imperfection, they don't give «exact» results, have limited precision and range, and require an extra data type. It is hard to understand what really goes on (How many digits of precision do we have today? Are perhaps 10-byte floats used for intermediate results? How does rounding behave?). For fixpoint support, the system must handle just integer arithmetics, I/O and string conversions. The rest is under programmer's control and responsibility (the essence of PicoLisp). Carefully scaled fixpoint calculations can do anything floating points can do.

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

это ведь от задачи, зато в простоте выигрыш

Ну да. «Пусть будет всё строка» (с) Perl, PHP, TCL.

А если серьёзно, то fixnum и float считаются на порядок быстрее, чем bignum и decimal.

Ликвидация массивов (а значит, и хэшей, и вообше всех структур с произвольным доступом) вообще гарантирует, что что-либо бульшое на таком языке не написать. Этакий sh со скобками.

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

Он живет в своем мире, всё ясно.

How many digits of precision do we have today? Are perhaps 10-byte floats used for intermediate results? How does rounding behave?

Это описывается в стандарте.

For fixpoint support, the system must handle just integer arithmetics, I/O and string conversions.

Но ведь у него нет и fixed point! Есть целые и, наверно, сдвиги. А остальное «сделай сам». К тому же мир не просто так придумал floating point с логарифмической шкалой.

зато в простоте выигрыш.

Но не в скорости. Сравнивая с тем же SBCL: если тип не указан компилятору явно с помощью declare, то он вызывает специальную функцию для сложения чисел (написанную на своём лиспо-ассемблере, кстати). Далее, если числа fixnum (а проверяется это по условию num&low_tag_mask == 0), вызывается add (машинная инструкция прям) и производится продвижение до bignum при надобности. Это уже много быстрее интерпретации и bignum'ов. А далее вызывается two-args-+, которая рассматривает остальные случаи в порядке убывания вероятности возникновения.

И, скажем так, если он чувствует, что система типов усложнена, пусть выкинет оттуда ratio и complex numbers, а не floating point, без которых уже никуда

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

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

А что, трудно разве навелосипедить это все на списках, или даже на тех же строках? Или Вы имеете в виду, большое, в смысле совместной разработки?

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

Ликвидация массивов

Да, я его поставил и посмотреть, как сделать там массив, и - сюрприз - кго там нет! И опять статья развенчание:

http://picolisp.com/5000/!wiki?ArrayAbstinence

Кстати, я нашел там map. А reduce там есть? Что-то не гуглится

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

Хотя где-то в своих проектах используешь?

Практиковался. Черт его знает чем это лучше объекта с слотом. Но определённо лучше чем:

(let ((list (list 1 2 3)))
  (append list (list 4)))
ados ★★★★★
()
Последнее исправление: ados (всего исправлений: 2)
Ответ на: комментарий от vonenij

Кстати, я нашел там map. А reduce там есть? Что-то не гуглится

Не, ну ведь мап и редъюс пишуться тривиально, нельзя же эти свистоперделки относить к реальным недостаткам дизайна языка. Это уж точно не по лисповски.

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

2 контраргумента:

1) В хорошем стандарте это должно быть, так как это настолько базовые вещи, что велосипедить их везде - это плохо.

2) Он писал, что у него «базовые узлы» (хз, что это у него, м.б. библиотечные функции) написаны на C. Тогда такой map должен быть быстрее. А если там нет TCO, то нормальной, в духе лиспа, реализации ты не напишешь

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

Черт его знает чем это лучше объекта с слотом

эээ... объект со слотом тождественен замыканию.

Я про то, что для сбора списка лучше использовать http://common-lisp.net/project/iterate/doc/ , который расширяем, позволяет обходить последовательности (а не только собирать значения).

Кстати, ещё одно идеологическое отличие CL и Scheme: в Racket очень-очень редко используется with-...

Те же коллекторы делались бы так:

(define new-collector
    (let ([store null])
      (lambda ([map (lambda (x) x)])
       (case-lambda
         [() (reverse store)]
         [(x) (set! store (cons (map x) store))]))))

(let ([col (new-collector)])
  (col 1)
  (col 2)
  (col 3)
  (col)) ; => '(1 2 3)

(let ([col (new-collector (lambda (x) (* 2 x)))])
  (col 1)
  (col 2)
  (col 3)
  (col)) ; => '(2 3 4)

... и писать ради функции на 5 строк целую библиотеку как-то жалко.

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

Чем не хеш?

Тем, что хэш имеет О(1) время доступа. А эта фигня О(N). И если про массивы он может и прав (кроме вычматематики сходу не вспомню, где мне нужен был массив не для последовательности, а для произвольного доступа), то как можно написать что-то большое без словарей, не представляю.

P.S. Интересно, у него символы внутри тоже в виде списка хранятся?

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

Хотя вопрос был риторический, да?

Да, это была, типа, шутка, но в каждой шутке есть доля шутки. Мне, как новичку, сейчас более интересны как раз велосипеды пока. Скорость меня мало интересует.

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

эээ... объект со слотом тождественен замыканию.

Значит дальше идет спор о предпочтениях и идеологиях.

Я про то, что для сбора списка лучше использовать http://common-lisp.net/project/iterate/doc/ , который расширяем, позволяет обходить последовательности (а не только собирать значения).

Я ниасилил её когда начались неповоротливости с уничтожением биндингов в секции (finally ...).

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

Внутри чего? Вы имеете в виду символы вроде

Я имею в виду символы car, cdr, list и прочие слова языка.

Где-то должно быть соответствие символ (слово) -> данные или функция. Вот мне и интересно, интерпретатор эту информацию тоже списком хранит?

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

неповоротливости с уничтожением биндингов в секции (finally ...).

Скажу честно, мне эта секция ни разу не была нужна :-)

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

STM-то чем крив? Клевая и удобная штука.

anonymous
()

Начинай с С, потом С++, Python, м.б. Java... Не думай о лиспе, пока не станешь программистом, не порти карьеру.

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

Я не знаю, как он реально реализован, врать не буду, читал где-то, что примитивы языка там вроде на ассемблере написаны. Но там декларируется полное соответствие кода и данных, там вроде не делается разницы между синтаксическим представлением символа и семантическим, поэтому, ЕМНИП, там можно сразу прочитать записанный символ:

(set 'a 1)
(set 'b (print a))
(print b); --> 1
Вроде так.

А в реализацию я не вникал глубоко, рановато мне еще.:)

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

Слушай, а вот допустим есть такая функция:

(defun foo ()
  (format *standard-output* "Hello world!"))

Насколько в sbcl сложно собрать все необходимые для запуска этой функции ассемблированного в отдельном файле где-нибудь в ~/.local/bin/ и удачно получить Hello world запуском из shell?

ados ★★★★★
()

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

с цианистого калия

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

На хабре есть статья , в которой автор отстаивает преимущества интерпретации.

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

Я пока не знаю, кому верить.

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

Батарейки можно писать и самому, например на C++, только собираются они часами. Можно на чистой сишке, но писать задолбаешься(уж больно уродливые получаются интерфейсы этих батареек).

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

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

справедливости ради замечу, что бинарное дерево никуда не делось. А у него доступ почти произвольный (O(log(N)). И ещё твои массивы сливают дереву на вставках/удалениях. А кеши не умеют делать выборки и доступ «к следующему».

Т.ч. в большинстве задач кеши и массивы и не нужны.

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

что бинарное дерево никуда не делось

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

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

А сам lisp там служит клеем, вместо которого с тем же успехом можно было-бы и bash заюзать.

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

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

Ну вот вспомнил.

Парсю файл по строкам и на последнюю строку определённые инструкции. Сделал я (iter (for sline :in-file path :reader #'read-line ... Чтобы распознать что в файле строка не последняя делаю сдвиг - первая итерация проверяет на конец, вторая - парсит и collect. Так вот когда конец файла цикл заканчивается и остаётся только (finally ... А оттуда collect уже не доступно.

Я взял collect из collectors. В iterate тоже могли бы взять их оттуда ( а ещё и reduce'ры).

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

То есть написал

(with-collector ... (iter ...))

Так в iterate тоже нужно коллектор делать внешним по отношению к сборщику:

(iter outer (for last in '(1)) 
            (iter (for sline in-file ...)
                  (setq last sline)
                  (in outer (collect (parse-every-line i))))
            (collect (parse-last-line last)))

monk ★★★★★
()

Вопрос лиспофагам: а что сейчас вообще пишут на лиспе? Ну как дропбокс на питоне, но только на лиспе.

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