LINUX.ORG.RU

CL


0

1

Помогите определиться с выбором:

SBCL, Clozure CL, CLISP. Может быть ещё что-то.

Критерии: наличие библиотек «на все случаи жизни», быстрота откомпилированного кода, удобство документации, наличие гуи-библиотеки, которая позволит сделать современный красивый интерфейс.

Спасибо.

p.s. и чтобы со SLIME работало.

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

> Конкретно, в Common Lisp нет ничего такого, что выделяло бы его возможности ФП по сравнению с многими другими языками, типа: JavaScript, Lua и т.д., которые никогда никто с ФП не связывает.

Ты действительно уверен, что в JavaScript и Lua есть функции высших порядков и лямбды?

Все-таки есть у Common Lisp возможности, которые его выделяют. Возьмем за основу последнюю статью из fprog#3. В CL есть так называемая «чисто функциональная структура данных» - гетерогенный список. На основе этого же списка легко имитируется «алгебраический тип данных» (в отличие от хаскеля, где список гомогенен). Во многих случаях простейшие проверки и destructuring-bind способны заменить «сопоставление с образцом». Написание «сверток» тоже не должно вызывать проблем.

Ну, пожалуй, к понятию ф.п. можно что-то еще прибавить. Готов расширить слегка определение. Уговорил :) Но CL должен ему подходить, иначе какой-то абсурд получится, чтобы лисп и не функциональный...

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

>Ты действительно уверен, что в JavaScript и Lua есть функции высших порядков и лямбды?

Будеш оспаривать очевидное?

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

> иначе какой-то абсурд получится, чтобы лисп и не функциональный...

лиспы разные бывают, никакого абсурда.

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

> Ты действительно уверен, что в JavaScript и Lua есть функции

высших порядков и лямбды?


Безусловно.

Все-таки есть у Common Lisp возможности, которые его выделяют.

...


какой-то абсурд получится, чтобы лисп и не функциональный...



Никакого абсурда. Изначально - да, лисп задумывался как функциональный. Но у него много замечательных свойств. И по мере его развития на первый план стали выходить именно эти свойства, а функциональная парадигма задвигалась всё дальше и дальше. Ещё раз даю ссылку на статью: http://lisper.ru/articles/common-lisp-technologies - здесь есть обзор основных отличительных свойств CL, к которому стоило бы ещё добавить мощнейшую систему символьных вычислений и рассказ о динамических свойства CL. Т.е. мы имеем следующие важные аспекты Common Lisp:

* Живая (динамическая) среда
* Символьное исчисление
* Макросистема
* CLOS
* Сигнальный протокол
* Работа со списками

Это наиболее характерные и важные свойства Common Lisp и среди их нет ничего, что имело бы какое либо отношение к ФП. Да, в CL очень важны функции, но это не функции в математическом понимании. Термин ФП очень обманчив, ибо кажется, что речь идёт о фукнциях, когда на самом деле речь идёт о функциях в математическом понимании, это очень важное отличие.

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

> http://lisper.ru/articles/common-lisp-technologies

Самый простой пример — макро AIF (или IF-IT), которое тестирует первый аргумент на истинность и одновременно привязывает его значение к переменной IT, которую, соответственно, можно использовать в THEN-clause:

s/THEN-clause/THEN- и ELSE-cluase/

мб как-то так?

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

> # Наконец, создание инфраструктурных систем языка. Например, с помощью макросов можно реализовать продления (библиотека CL-CONT), ленивые вычисления (библиотека SERIES) и т.д.

s/продления/продолжения/

?

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

кажется, что речь идёт о фукнциях, когда на самом деле речь идёт о функциях в математическом понимании

глубокомысленно

Сигнальный протокол

а это что такое? MOP?

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

> Это наиболее характерные и важные свойства Common Lisp и среди их нет ничего, что имело бы какое либо отношение к ФП.

Лисп бесподобно многогранен, что мне особенно нравится в нем. Я думаю, что после хорошего освоения хаскеля и окамла может открыться еще одная сторона лиспа, функциональная.

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

> А вот макросы чтения выполняются еще на этапе обработки программы парсером при обнаружении специальных символов (dispatch characters).

не только диспатчь же. или ты только перевел статью?

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

не, это про кондишны/рестарты

а. хорошая штука, факт

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

> не только диспатчь же. или ты только перевел статью?

Статья вообще не моя, там есть ссылка и на оригинал и на блог автора.

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

> Статья вообще не моя, там есть ссылка и на оригинал и на блог автора.

ага, я просто на заголовок посмотрел после того как... =)

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

Мде, одной статьей ты снял с меня все недопонимания в механизме работы ExtJS, например. В букмарки.

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

Это наиболее характерные и важные свойства Common Lisp и среди их нет ничего, что имело бы какое либо отношение к ФП.

Мне иногда кажется, что ты просто не читаешь то, что я пишу.

Лисповский список имеет самое прямое отношение к ф.п. Символьные данные тоже можно привлечь, например, к созданию алгебраических типов данных.

  data TaggedType a = SingleValue a | DoubleValue (a, a)

Контрукторы данных переводятся на лисп элементарно. При желании можно зашаблонировать макросом.

  (defun single-value (a)
    (list 'single-value a))

  (defun double-value (a1 a2)
    (list 'double-value a1 a2))

Потом где-нибудь в коде.

  (defun test-tagged-type (v)
    (ecase (car v)
      (single-value (format t "SingleValue ~A" (cadr v)))
      (double-value (format t "DoubleValue (~A, ~A)" (cadr v) (caddr v)))))
dave ★★★★★
()
Ответ на: комментарий от dave

Дальше больше.

Мы можем определить утилиты.

(defmacro define-adt (name &rest args)
  `(defun ,name (,@args)
     (list ',name ,@args)))

(defmacro adt-case (value &body cs)
  (let ((ps (loop for c in cs collect 
		 (destructuring-bind ((name &rest args) &body body) c
		   (adt-pattern value name args body)))))
    `(ecase (car ,value) ,@ps)))

(defun adt-pattern (value name args body)
  `(,name
    ,(if (null args)
	 `(progn ,@body)
	 `(destructuring-bind (,@args) (cdr ,value) ,@body))))

Тогда все наши определения запишутся короче.

(define-adt none-value)
(define-adt single-value a)
(define-adt double-value a1 a2)

(defun test-tagged-type (v)
  (adt-case v
    ((none-value) (format t "NoneValue"))
    ((single-value a) (format t "SingleValue ~A" a))
    ((double-value a1 a2) (format t "DoubleValue (~A, ~A)" a1 a2))))

И это по-прежнему в своей основе ф.п., точнее ADT!

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

> Мне иногда кажется, что ты просто не читаешь то, что я пишу.

Читаю.

Лисповский список имеет самое прямое отношение к ф.п.


Хм.. Разве это не просто набор связанных CONS-ячеек?

Символьные данные тоже можно привлечь, например,

к созданию алгебраических типов данных.



А при чём здесь это?

Как здесь любят повторять «настоящий программист на любом языке будет писать как на фортран» :) Т.е. можно придумывать всякие фокусы, особенно с учётом того, что в CL имеет мощная макросистема. Но это не сделает из Common Lisp ФЯП.

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

> Хм.. Разве это не просто набор связанных CONS-ячеек?

Нет, не просто. В CONS-ячейке заложен большой смысл. В ней очень много от ф.п. Запредельно много. «Чисто функциональная структура данных» + благодаря гетерогенности (динамизму языка) основа для построения «алгебраических типов данных». В кавычках термины из последней статьи fprog#3.

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

А идею макросов для ADT, пожалуй, надо развить. Может быть, напишу что-нибудь потом. :)

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

>> Но это не сделает из Common Lisp ФЯП.

ОК. Тогда какая разница между ФЯП и чистым ФЯП? Это два тождественных понятия?

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

> В CONS-ячейке заложен большой смысл. В ней очень много от ф.п.

Ради бога, я думаю их свойства обусловлены прежде всего особенностями железа, для которого делались первые реализации лисп :) Благо, car и cdr, если мне память не изменяет, просто названия регистров на тех машинах.

Тогда какая разница между ФЯП и чистым ФЯП?

Это два тождественных понятия?



Чистый ФЯП подразумевает, что всегда используется подстановочная модель вычислений. «Нечистый» ФЯП, вероятно, допускает некоторые отклонения от этого в специально оговоренных и понятных для компилятора/интерпретатора случаях. В Common Lisp всегда используется «продвинутая» схема вычислений с окружением, не зависимо от того, как именно написанная конкретная функция.

Ну, да ладно. Пусть каждый видит лисп таким каким хочет.

Язык позволяет это в отличие от многих других языков.



Ну, мое мнение основано на анализе исходных кодов различных проектов, и в коих признаки ФП найти достаточно тяжело.

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

>Благо, car и cdr, если мне память не изменяет, просто названия регистров на тех машинах.

Названия мнемоник для работы с регистрами.
Contents of the Address part of the Register
и
Contents of the Decrement part of the Register

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

> не чистая она никакая

Чистота иногда мешает. В том числе в ф.п. :)

На примере F# видно, что есть много примеров функций, которые внешне выглядят чистыми, а внутри используют совершенно «грязные» методы для повышения эффективности. Да в том же лиспе используются PUSH и NREVERSE вместе для работы с внутренним аккумулятором.

Кроме того, мне кажется, что есть целый класс функций, которые как бы являются получистыми. Возьмем моделирование. Я придумал простую монаду для представления динамических процессов, интегрируемых методами Рунге-Кутта и Эйлера. Проблема в том, что такие процессы недетерменированы (стохаcтистические) по своей сути. Каждый новый прогон - новые результаты. Такая монада легко реализуется на F# и лиспе. На F# у меня уже есть готовый рабочий образец. Может быть, сделаю для лиспа. Но я совершенно не представляю, как это сделать в хаскеле. Нужна недетерменированность и непременно мемоизация внутри одного прогона (монады). Тупик. Хотя, возможно, я слабо владею хаскелем...

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

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

>> На примере F# видно, что есть много примеров функций, которые внешне выглядят чистыми, а внутри используют совершенно «грязные» методы для повышения эффективности

Вот тут archimag нападал на CL с претензией, что функции CL реализованы не в стиле ФП, независимо от того, что о них думает программист, даже если внешне эти функции чистые. При это скромно обошел вниманием повальное использование unsafePerformIO и аналогичных в исходниках Prelude.

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

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

На каких основаниях?

Вот прямое определение (правда из Википедии, но нормальное):

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

Т.е. ФП определяются именно через чистоту. Или вы знаете другое определение ФП?.

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

> от тут archimag нападал на CL с претензией,

что функции CL реализованы не в стиле ФП


Я не нападал на CL, наоборот, я защищаю Common Lisp от ФП, т.е. от устаревших догм, что лисп это якобы функциональный язык.

При это скромно обошел вниманием повальное использование

unsafePerformIO и аналогичных в исходниках Prelude



Я даже не знаю, что такое unsafePerformIO и Prelude :(

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

>> Я не нападал на CL

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

Я даже не знаю, что такое unsafePerformIO и Prelude :(

ВНЕЗАПНО!

Т.е. ты рассуждаешь о свойствах ФЯП, приводишь в качестве примера Хаскель, не написав на нем ни строчки? Шикарно!

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

2 archimag

В математике есть понятие «критерий», его формулировка обычно состоит из двух частей: необходимости и достаточности. Так вот, твое определение ФЯП, как я зыка, чьи вычислительные процессы целиком и полностью укладываются в подстановочную модель (при этом «модель» в изначальном ее смысле, как приближенного описания, точно такой смысл в это вкладывается в SICP) является достаточным условием, но не необходимым, т.е. язык может реализовывать парадигму ФП в полной мере будучи описываемым любой моделью вычислений, но язык не выходящий за рамки подстановочной модели не может реализовать ничего кроме парадигмы ФП. И первый и второй язык можно считать ФЯП применительно к парадигме. Ферштейн?

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

> Т.е. ты рассуждаешь о свойствах ФЯП, приводишь в качестве примера

Хаскель, не написав на нем ни строчки?


Я не понял, что не так? Что бы привести в пример Haskell мне не надо на нём писать. Впрочем, я посвятил ему около месяца три года назад (и к своему счастью уже давно всё забыл). Как бы там ни было, основной источник, на который я ссылаюсь - это SICP.

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

> Так вот, твое определение ФЯП, как я зыка, чьи вычислительные

процессы целиком и полностью укладываются в подстановочную модель


Это не мое определение. И оно непосредственно следует из определения ФП.

язык может реализовывать парадигму ФП в полной мере

будучи описываемым любой моделью вычислений



Нет. Так можно говорить о конкретной программе (или алгоритме), что она написана в стиле ФП, но не о языке.

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

> Т.е. ФП определяются именно через чистоту. Или вы знаете другое определение ФП?.

Не стоит дословно понимать определения из википедии. В математике есть случайные величины. Даже стохастические интегралы есть с мартингалами. Далеко не все математические объекты можно переложить в примитивные типы данных компьютера. Между ними пропасть. Поэтому чистота в математике и чистота в хаскеле - вещи разные.

И потом, не забывай об окамле и f#. В них тоже есть побочные эффекты и мутабельность.

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

> Вот тут archimag нападал на CL с претензией, что функции CL реализованы не в стиле ФП, независимо от того, что о них думает программист, даже если внешне эти функции чистые. При это скромно обошел вниманием повальное использование unsafePerformIO и аналогичных в исходниках Prelude.

Очень интересное наблюдение про хаскель.

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

>> Что бы привести в пример Haskell мне не надо на нём писать.

Хорошо опустим это. Prelude - это стандартная библиотека хаскеля, ф-ции с префиксом unsafe - ф-ции с побочными эффектами (нечистые).

Нет. Так можно говорить о конкретной программе (или алгоритме), что она написана в стиле ФП, но не о языке.

Тогда опять вернемся к моему вопросу отличий чистых от нечистых ФЯП. Мы говорим примерно об одном, только каждый о своем :) Я не вижу причин считать лисп не ФЯП языком. Так же как не ООП, не языком логического, аспект-ориентированного и еще чего там есть программирования, если он поддерживает все эти парадигмы. Вплоть до того, что лисп - язык символьной алгебры, проектирования электронных схем, язык чтоб грабить караваны и вообще все что угодно. И в каждой области писать программы одинаково легко, во всяком случае ФП делается не сложнее чем в хаскеле. Вот и рассматриваю я принадлежность языка к ФЯП исключительно с инженерной позиции - есть нужные средства, значит ФЯП. Средства - это абстракции, структуры данных и т.д. Тем более, что если это нет в лиспе, то валяй пиши свое, делай DSL обзови его ФЯП.

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

Не стоит дословно понимать определения из википедии.

Ну так я предложил привести другое. А приведённое определение хорошо соответствует тому, о чем я читал ранее.

В математике есть случайные величины.

Э... можно ссылку? Что-то я не пойму, что вы имеете в виду.

Поэтому чистота в математике и чистота в хаскеле - вещи разные.

Не понял, что за чистота в математике? По отношению к математике мне этот термин не понятен...

И потом, не забывай об окамле и f#.

В них тоже есть побочные эффекты и мутабельность.

Про это уже говорили выше:

Чистый ФЯП подразумевает, что всегда используется подстановочная модель вычислений. «Нечистый» ФЯП, вероятно, допускает некоторые отклонения от этого в специально оговоренных и понятных для компилятора/интерпретатора случаях. В Common Lisp всегда используется «продвинутая» схема вычислений с окружением, не зависимо от того, как именно написанная конкретная функция.

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

Про интегралы не понял.

И потом, не забывай об окамле и f#. В них тоже есть побочные эффекты и мутабельность.

И они считаются функциональными. Потому, что так написано в спецификации/стандарте :)

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

> Я не вижу причин считать лисп не ФЯП языком.

Хорошо. Давайте тогда начнём с того, что ассемблер позволяет писать в любой парадигме и следовательно также поддерживает ФП, ООП, и т.п. Или, например для языка C есть GObject, однако ведь никто не пытается причислить C к объектно-ориентированным языкам. Почему? Да просто потому, что язык C не предоставляет никаких средств для поддержки ООП, хотя и на нём можно писать в стиле ООП. Когда мы говорим, что какой-то язык поддерживает конкретную парадигму, то подразумевается, что в данном языке есть специальная поддержка для этого, которая делает программирование в подобном стиле простым, а результирующий код приемлемо эффективным. ФП в языках без специальной поддержки этого жутко неэффективно (это правда), как правило не имеет необходимой выразительной силы, и по большей части не имеет особого смысла. Однако, для ФЯП оно (ФП) обретает определенную силу, основанное на одноименной области математики, которая предоставляет необходимый набор выразительных средств, может предоставить определённый уровень гарантий относительно безошибочности года и позволяет сделать результирующий код довольно эффективным с точки зрения машинных ресурсов. Никакой особой поддержки для ФП в Common Lisp нет (если сравнивать с другими языками, типа JavaScript, Lua, Perl, Python и т.п.). Поэтому я и говорю, что Common Lisp такой же ФЯП, как C язык ООП.

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

Про математику я имел ввиду, что «вычисление значений функций в математическом понимании последних» и вычисление функций на хаскеле - это две большие разницы. Функция в математике, например, может вычисляться как конечный предел бесконечной последовательности или как бесконечная рекурсия, что на компьютерах осуществить невозможно. В общем, мне просто не нравится то определение из википедии.

Еще я думаю, что определений ф.п. может быть вагон и маленькая тележка. Просто лисп является ф.я.п. и точка :)

«Нечистый» ФЯП, вероятно, допускает некоторые отклонения от этого в специально оговоренных и понятных для компилятора/интерпретатора случаях.

Для окамла никаких оговорок быть не может. Подстановочная модель для него не работает в принципе. «Нечистый» окамл отличается от лиспа главным образом статической типизацией. Других отличий в функциональных фишках пока не заметил.

Вообще-то, по большому счету и хаскель из-за unsafePerformIO не является кристально чистым, но это опять же больше терминологический вопрос :) Хотя вот для хаскеля некоторые оговорки в подстановочной модели все же возможны, но только для него.

Ты бы окамл выучил. Его база проста. Осваивается за пару дней по хорошему учебнику. А то ходим кругами, и каждый твердит свое.

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

> В общем, мне просто не нравится то определение из википедии.

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

Просто лисп является ф.я.п. и точка :)


Что за язык лисп? Если говорить про Common Lisp, то ... на преодоление некоторых предрассудков может потребоваться время :)

Впрочем, я могу предложить ещё один критерий: реальная практика. Какие проекты на Common Lisp реализованы в функциональном стиле? Я что-то ничего не припоминаю...

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

>archimag (*) (28.01.2010 15:34:44)

archimag или всё же architroll?

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

> Впрочем, я могу предложить ещё один критерий: реальная практика. Какие проекты на Common Lisp реализованы в функциональном стиле? Я что-то ничего не припоминаю...

Нужны примеры применения ф.п. в CL? Вот, очень наглядно. Код главы 27 книги Practical Common Lisp написан в функциональном стиле. Безоговорочно. Как раз сейчас читаю.

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

> Вот, очень наглядно. Код главы 27 книги Practical Common Lisp

Он же кишит CLOS, динамическими переменными и сильно-императивным loop?

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

> около 75% самого CL.

Очень интересно, а что это такое «сам CL»? Где посмотреть исходный код? И как производилась оценка?

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

> Очень интересно, а что это такое «сам CL»? Где посмотреть исходный код? И как производилась оценка?

вероятно имеются в виду функции и макры, входящие в стандарт ACL

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

чем clos не подходит?

(defclass adt () ())
(defclass none-value (adt) ())
(defclass single-value (adt)
           ((x :accessor  a1)))
(defclass double-value (adt)
           ((x :accessor  a1) 
            (y :accessor a2)))

(defgeneric adt-print (x))
(defmethod adt-print ((x none-value))
           (print "none"))
(defmethod adt-print ((x single-value))
           (format t "single ~A" (a1 x)))
(defmethod adt-print ((x double-value))
           (format t "double ~A ~A" (a1 x) (a2 x)))

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

(defmacro def-adt (name (&rest forms))
           (labels ((expand (forms res)
                    (if (null forms) res
                        (let ((val (car forms)))
                          (expand (cdr forms)
                                  (cons (list val :accessor val) res))))))
             `(defclass ,name (adt)
                ,(expand forms nil))))

можно ещё завернуть определение expand в какой-нибудь сахар в виде паттерн матчинга на основе destructuring-bind.

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

P.S. forms - чисто функциональные.

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

> можно ещё завернуть определение expand в какой-нибудь сахар в

виде паттерн матчинга на основе destructuring-bind.


Угу, что бы получился полноценный костыль, который в реальном коде никто использовать не будет... И это вы называете ФП? В топике явно не хватает хаскелистов :))

P.S. Кстати, поведение print и format сильно зависит от текущего окружения...

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