?

Log in

Почему LISP? - Жить не можем без проблем! [entries|archive|friends|userinfo]
Жить не можем без проблем!

[ userinfo | livejournal userinfo ]
[ archive | journal archive ]

Почему LISP? [Jan. 13th, 2011|02:05 pm]
Жить не можем без проблем!

ru_lisp

[aralex]

Как говорил Ворошилов, вопрос к Знатокам (к знатокам LISP-а в данном случае)! Почему таки LISP? Или, если конкретнее, вопроса три:

  1. Для каких именно задач LISP подходит больше, чем другие языки?
  2. За счёт чего для них он подходит больше?
  3. В чём именно выражается его преимущество?

Если не в лом, приведите, pls, коротенькие иллюстрации на LISP-е (или ссылочку на них). Заранее благодарен!

Исходно данный пост был размещён в сообществе ru_programming, но там Знатоков, способных ответить внятно и по сути, увы, не нашлось :(

linkReply

Comments:
From: (Anonymous)
2011-01-16 11:10 am (UTC)
То, что лисп мультипарадигменный - заблуждение, если только не считать способы декомпизиции (функциональная, объектная и т.д.) парадигмами, ну а тогда все языки мультипарадигменные. Парадигма там одна - императивное программирование. Декларативно в лиспе писать нельзя (нет, в теории можно встроить декларативный язык, но на практике никто так не делает и делать не будет, потому как все библиотеки императивные и вообще инфраструктура не способствует), а вот Хаскель поддерживает обе парадигмы.
(Reply) (Parent) (Thread)
[User Picture]From: grundik
2011-01-16 11:48 am (UTC)
Ээээ... На лиспе можно писать так, как хочется.
Декларативно - это как, по-вашему? Как в прологе? Lisa работает, я проверял.

Но в общем неважно. Важно, что лисп не функциональный язык.
(Reply) (Parent) (Thread)
From: (Anonymous)
2011-01-16 12:36 pm (UTC)
"Ээээ... На лиспе можно писать так, как хочется."
Ну понятно, настоящий коммунизм - сегодня в колбасе потребности нет, сегодня декларативно писать в лиспе не хочется.

Декларативность - это просто. Когда мы получаем один результат вне зависимости от пути редукции. В декларативном языке, например,
map f . map g == map (f . g)
В императивном - так может быть в зависимости от везения и фазы луны, но в общем случае, разумеется:
map f . map g != map (f . g)
Потому что f и g не функции и процедуры и могут изменять глобальные переменные, читать файлы, запускать межконтинентальные ракеты.

И, конечно, это не как в Прологе. Пролог - императивный, хоть и имеет декларативное подмножество. Но помимо этого красные каты, императивные как бы предикаты, да там можно из "базы знаний" викидывать и добавлять предикаты прямо во время выполнения - о какой декларативности вообще разговор.

"Важно, что лисп не функциональный язык."
Не всякий. Коммон лисп, конечно, не функциональный. А схема - функциональный, но императивный. Как СМЛ или, ха-ха, сишарп.
(Reply) (Parent) (Thread)
[User Picture]From: grundik
2011-01-16 01:26 pm (UTC)
Эммм... Зачем нужен софт, который ничего не делает? Ну то есть в файлы не пишет, ракеты не запускает? Это на тему "в колбасе потребности нет", ога.

По остальному комментировать не хочу, ибо жонглирование терминами таки не мой конёк.
(Reply) (Parent) (Thread)
From: (Anonymous)
2011-01-16 01:43 pm (UTC)
Само собой разумеется, что софт, который ничего не делает, не нужен.
Как не нужен и софт, который делает не то что надо, и запускает ракеты вместо записи в файл, а в файл пишет вместо запуска ракет.
Только писать в файл, запускать ракеты и вообще программировать императивно в деларативном языке можно, и состояние и последовательность выполнения всегда будет под контролем. А вот программировать декларативно на императивном языке нельзя. Как нельзя и контролировать состояние с последовательностью действий. Т.е. в императивном языке и возможностей работать с состоянием меньше, чем в декларативном.
(Reply) (Parent) (Thread)
[User Picture]From: thesz
2011-01-16 03:38 pm (UTC)
Этот софт гарантировано корректно и правильно вычисляет необходимость записи в файл и запуска ракет.
(Reply) (Parent) (Thread)
From: (Anonymous)
2011-01-16 03:57 pm (UTC)
> Декларативность - это просто. Когда мы получаем один результат вне зависимости от пути редукции. В декларативном языке, например,
map f . map g == map (f . g)

Если map и . чистые (что гарантируется исключительно реализацией языка, хоть в хаскеле, хоть в лиспе) то это равенство будет выполняться, при условии, что вычисления энергичны и порядок выполнения аргументов фиксирован. Например, в Common Lisp оно выполняется.
(Reply) (Parent) (Thread)
From: (Anonymous)
2011-01-16 06:13 pm (UTC)
1)Ну а как вы гарантируете чистоту функций f и g?
2)Нет, не выполняется. Подумайте лучше.
(Reply) (Parent) (Thread)
From: (Anonymous)
2011-01-17 04:20 am (UTC)
> 1)Ну а как вы гарантируете чистоту функций f и g?

Я же говорю - они гарантируются реализацией. То есть дяди, которые писали эти функции, говорят "мамой клянусь, функции чистые". Никакой другой гарантии тут нет ни в лиспе, ни в хаскеле. В крайнем случае, эти функции используют некоторые функции, которые "мамой клянусь, чистые".

> 2)Нет, не выполняется. Подумайте лучше.

Выполняется, потому что порядок вычисления f и g в обеих частых равенства совпадает, а остальное - "чистое"..
(Reply) (Parent) (Thread)
From: (Anonymous)
2011-01-17 09:34 am (UTC)
"дяди, которые писали эти функции, говорят "мамой клянусь, функции чистые". Никакой другой гарантии тут нет ни в лиспе, ни в хаскеле."

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

"порядок вычисления f и g в обеих частых равенства совпадает, а остальное - "чистое""

Ох, ну я же говорил, подумайте лучше. Порядок вычисления f и g не совпадает - в этом суть примера.
map f . map g -> gggfff
map (f . g) -> gfgfgf
если они чистые - нет разницы, если не чистые - разница есть и еще какая.
Реализатор map никак не может написать чистую функцию, потому что ее чистота зависит от чистоты функции, к которой она применяется. И в императивном языке не существует гарантий на эту самую приходящую из вне функцию, которые можно использовать на практике. И поэтому, на практике никто не будет, находясь в здравом уме, делать такое преобразование, потому что норма - сайд-эффект. А в декларативном будут - потому что там норма - чистая функция и от процедуры ее можно отличить. Вот и вся разница.
(Reply) (Parent) (Thread) (Expand)
(no subject) - (Anonymous) Expand
(no subject) - (Anonymous) Expand
(no subject) - (Anonymous) Expand
(no subject) - (Anonymous) Expand
(no subject) - (Anonymous) Expand
(no subject) - (Anonymous) Expand
(no subject) - (Anonymous) Expand
(no subject) - (Anonymous) Expand
(no subject) - (Anonymous) Expand
[User Picture]From: thesz
2011-01-16 06:20 pm (UTC)
Вы подписывайтесь, пожалуйста. Страна должна знать своих героев.

Завести login в ЖЖ очень просто, а нам приятно будет говаривать между собой "А, опять N! Ну, с мы его по дискуссии в ru_lisp хорошо знаем."
(Reply) (Parent) (Thread)
[User Picture]From: love5an
2011-01-17 03:43 pm (UTC)
ой, блядь.
ну вот это такая хуйня, что я пройти мимо не могу.

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

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

Кроме того, см. хотя бы в википедию на тему того, что такое "парадигма программирования" - http://en.wikipedia.org/wiki/Programming_paradigm
чтобы не нести больше такого бреда
(Reply) (Parent) (Thread)
From: (Anonymous)
2011-01-17 04:26 pm (UTC)
"ой, блядь.
ну вот это такая хуйня, что я пройти мимо не могу."

Дышите глубже, вы взволнованы.

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

Забавно, и, наверное, годится для объяснения детям или введение в заблуждение менеджеров. Правда отдает какой-то схоластикой, дальше наверное следует переход к спору о терминах и о том, сколько ангелов помещается на кончике иглы. С тем определением, что я привел, конечно так не получится. Если мы принимаем, что декларативность - это независимость результата от порядка вычислений, то, например, имея теорему Черча-Россера сразу получаем что лямбда-исчисление (без расширений, например, мутабельными ячейками) декларативно. Флеймоемкость нулевая. А из вашего получится настоящий вечный огонь.

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

А, извините, не признал. Конечно, конечно. Лисп луччей! Не беспокойтесь, я с вами спорить не стану.
(Reply) (Parent) (Thread)
[User Picture]From: love5an
2011-01-17 06:13 pm (UTC)
Декларативность это независимость не только от порядка вычислений, но и от вида вычислений, от структур данных, в вычислениях используемых, и так далее. Это вообще независимость от вычислений.

Декларативная конструкция - описание, спецификация объекта предметной области.

Хаскель не декларативен. CL, в базовой форме - тоже. Но, в отличие от хаскеля, CL позволяет вводить декларативные конструкции, макросами. Хаскель же ограничен теми сущностями, которыми он оперирует. Типами, монадами, функциями, туплами, списками и так далее. Если подумать, хаскель намного более императивен, чем CL.

Лямбда-исчисление тоже дофига императивно. Описывает процесс вычислений потому что.
(Reply) (Parent) (Thread)
From: ext_55374
2011-01-17 10:08 pm (UTC)
> Но, в отличие от хаскеля, CL позволяет вводить декларативные конструкции, макросами.

Толку с этих конструкций, если решение всё равно надо руками набивать?

> Хаскель же ограничен теми сущностями, которыми он оперирует.

Бггг. Лисп, наверное, може оперировать даже теми сущностями, которыми он не оперирует? :)
(Reply) (Parent) (Thread)
[User Picture]From: love5an
2011-01-17 11:30 pm (UTC)
>Бггг. Лисп, наверное, може оперировать даже теми сущностями, которыми он не оперирует? :)

Common Lisp может абстрагировать от примитивов языка(функций, структур данных, типов, и так далее). Хаскель - нет.

>Толку с этих конструкций, если решение всё равно надо руками набивать?

Дак в том и фишка, что не надо.

Яркий пример - ASDF. Она вводит макрос defsystem, декларативную спецификацию модуля, т.е. грубо говоря, набора исходников, которые надо скомпилировать и/или загрузить в лисп-систему и/или протестировать в определенном порядке.

И потом, мы просто говорим (asdf:load-system :system-name), например, и безо всяких дополнительных телодвижений получаем скомпилированный код, подгруженный в лисп-систему.

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

Так вот, для определения сишных функций, которые отображаются в лисп нам не надо описывать руками процесс перевода байтов из памяти в лисп и назад - мы просто описываем функцию, ее типы, в декларативной форме, и получаем готовую лисповую функцию, которую можно использовать с лисповыми же объектами - никакого ручного маршалинга, все автоматически, и причем, код для маршалинга генерируется достаточно эффективный - так как анализ типов происходит во время компиляции - никакого диспатча в рантайме.
(Reply) (Parent) (Thread)
From: ext_55374
2011-01-18 12:14 am (UTC)
> Common Lisp может абстрагировать от примитивов языка(функций, структур данных, типов, и так далее). Хаскель - нет.

Что это значит и как выглядит на практике?

> Она вводит макрос defsystem, декларативную спецификацию модуля, т.е. грубо говоря, набора исходников, которые надо скомпилировать и/или загрузить в лисп-систему и/или протестировать в определенном порядке.

Честно говоря, так и не понял, чем это от import blabla отличается. Да и набор исходников упомянутый не из воздуха появляется.

> Другой пример - моя библиотека Virgil

Ага, значит таки библиотека. Библиотеку руками писали, или декларировали «хочу, чтоб всё было в шоколаде»?

И чем это отличается от

import MyModules.Pizdato

main = make_pizdato ("put/your/function/here", tralivali)

?
(Reply) (Parent) (Thread) (Expand)
From: (Anonymous)
2011-01-18 09:50 am (UTC)
"Декларативная конструкция - описание, спецификация объекта предметной области"

Вы все упорствуете, а ведь ваше определение бессодержательно. Получается что foo.money - это декларативно, а foo.getMoney() императивно. Но тогда декларативно можно писать вообще на всех языках.

На перл про ограничение сущностями, которыми оперирует уже тут рядом указали.

"Хаскель не декларативен."

Он декларативен, потому как это типизированное лямбда-исчисление без cell и с чистым IO.

"Если подумать, хаскель намного более императивен, чем CL"

Полагаю, вы так думаете потому, что вы фанат лиспа. Императивность/декларативность это не вопрос добра или зла, но вы кинулись защищать свой лисп, а смысл - кого он волнует? Если бы кто-нибудь написал "в замкнутой системе импульс сохраняется", то вы бы, наверное, бросились во имя великой справедливости писать, что "если подумать, импульс сохраняется в замкнутой системе намного хуже, чем ЛИСП". А чем хуже? Да очевидно же: чем ЛИСП.

"Лямбда-исчисление тоже дофига императивно. Описывает процесс вычислений потому что."

Мощное заявление. Давайте ссылку на опровержение доказательства теоремы Черча-Россера.
(Reply) (Parent) (Thread)
From: (Anonymous)
2011-01-18 09:28 am (UTC)
> Если мы принимаем, что декларативность - это независимость результата от порядка вычислений, то, например, имея теорему Черча-Россера сразу получаем что лямбда-исчисление (без расширений, например, мутабельными ячейками) декларативно.

А если не принимаем, то не получаем. Поскольку общепринятому определению декларативности придуманное вами определение не соответствует, то я предпочту не принимать. А то так можно до чего угодно наприниматься, вот, например, если принять, что 5 - это 4, то 2*2=5. Отсюда и из аксиом арифметики сразу следует, что все числа равны нулю.
(Reply) (Parent) (Thread)
From: (Anonymous)
2011-01-18 10:10 am (UTC)
"А если не принимаем, то не получаем."

Да, конечно. Отрицание это нормальная реакция.

"общепринятому определению декларативности придуманное вами определение не соответствует"

Общепринятому в ru_lisp? Допускаю. И, вообще-то, его не я придумал. Точно, правда, не помню кто (может быть Ландин?) но я считал его общепринятым. Оно, например, примерно в таком виде есть в классическом учебнике по ФП Джона Харрисона. В третьей главе.

"то я предпочту не принимать"

Ваш выбор.
Какое, кстати, определение общепринято в lisp_ru? Я не постоянный читатель, как-то упустил.
(Reply) (Parent) (Thread)
From: (Anonymous)
2011-01-18 11:50 am (UTC)
> Какое, кстати, определение общепринято в lisp_ru?

А при чем тут ru_lisp? Я говорю об общепринятом понимании этого термина. Декларативность предполагает работу с данными, а не с процессом их обработки. Никакого ограничения на модель вычисления тут нет. Да и вообще - какая модель вычисления у XML, например? А ведь это один из лучший примеров декларативности.
(Reply) (Parent) (Thread)
From: (Anonymous)
2011-01-18 12:19 pm (UTC)
"Я говорю об общепринятом понимании этого термина."

А я спрашиваю - общепринятым кем? Ощепринятым где?

"Декларативность предполагает работу с данными, а не с процессом их обработки."

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

"Никакого ограничения на модель вычисления тут нет."

Ограничение на модель вычислений таки есть - если у нас полнота по Тьюрингу, есть _|_ и это влияет на семантику.

"Да и вообще - какая модель вычисления у XML, например?"

А тут нет тьюринг-полноты, нет _|_ а потому любая. Как его не вычисляй - результат не поменяется. И понятно, от пути вычисления зависимости нет.

"А ведь это один из лучший примеров декларативности."
Я так не думаю. Рассуждать о декларативности применительно к чисто описательным, неполным по тьюрингу языкам совсем не интересно - слишком просто все.
(Reply) (Parent) (Thread) (Expand)
(no subject) - (Anonymous) Expand
(no subject) - (Anonymous) Expand
(no subject) - (Anonymous) Expand
(no subject) - (Anonymous) Expand
From: ext_55374
2011-01-17 06:01 pm (UTC)
> Так вот макросы позволяют настолько декларативно писать, что никакие хаскели и рядом не лежали.

Постановку задачи — может быть. Процесс решения — ну никак, нужна имперетивщина и explicit функциональщина.

Простейший пример: решение полиномиального уравнения с одной переменной. Декларативная постановка: «найти такой x, что x^10 - 2 * x ^ 7 + 4 = 0». И всё, тупик. Нужен солвер, который уже реализует перебор, деление пополам или метод Ньютона.

Толку с такой «декларативности без процесса», если это одна строчка, и не самая важная?
(Reply) (Parent) (Thread)
[User Picture]From: love5an
2011-01-17 07:28 pm (UTC)
ну да, декларативность это не серебряная пуля
(Reply) (Parent) (Thread)
From: (Anonymous)
2011-01-19 03:01 pm (UTC)
Количество толка станет очевидно, как только уравнений окажется 100500, пачками, в течении нескольких месяцев, список уравнений сопровождается операторами со низкой квалификацией. И солверов несколько, выбирать надо по виду уравнения.
(Reply) (Parent) (Thread)