LINUX.ORG.RU

CL


0

1

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

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

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

Спасибо.

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

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

>И это вы называете ФП?

да. но поскольку в лиспе богатые возможности для ФП, вместо записи итерации вручную через рекурсию, можно использовать готовую функциональную конструкцию CL:

[code] (defmacro def-adt (name (&rest forms)) `(defclass ,name (adt) ,(mapcar (lambda (x) (list x :accessor x)) forms))) [/code]

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

И это вы называете ФП?

да. но поскольку в лиспе богатые возможности для ФП, вместо записи итерации вручную через рекурсию, можно использовать готовую функциональную конструкцию CL:

(defmacro def-adt (name (&rest forms)) 
           `(defclass ,name (adt) 
              ,(mapcar (lambda (x)
                         (list x :accessor x))
                         forms)))
anonymous
()
Ответ на: комментарий от archimag

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

Ты смотри на реализацию SELECT. И даже LOOP можно использовать вполне в рамках ф.п. Ты боись деструктивного присваивания :)

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

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

Мой метод по сути не зависит от конкретного представления. При желании можно и через CLOS реализовать. Но я не понял как тогда реализовать хотя бы частично pattern-matching как у меня. Нужно, чтобы adt-case могли быть вложенными. Это важно. Главное - adt-case.

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

> сильно-императивным loop?

Кстати, использовать for и while и даже ref с mutable - обычная практика при реализации чистых функций в окамле и f#. Чистота она относительна. Относительно того, как какая-то функция выглядит извне. Или относительно того, какими методами она реализована. Это разные вещи.

В общем, ф.п. бывает разным.

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

>Чистота она относительна.

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

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

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

Кстати о loop. Внутреннюю функцию expand можно переписать иначе через loop. Тогда порядок объявления слотов будет прямым. И как ни странно, такая функция будет вполне ф.п.-комильфо.

(defun expand (forms)
  (loop for f in forms collect (list f :accessor f)))
dave ★★★★★
()
Ответ на: комментарий от dmitry_vk

(утомленно) Сразу спрашиваю, чтобы сэкономить время. С окамлом и f# знаком? И с unsafePerformIO из хаскеля?

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

dave, учи матчасть

 data TaggedType a = SingleValue a | DoubleValue (a, a) 
(deftype tagged-type (a)
    `(or (single-value ,a) (double-value ,a ,a)))
Хотя из исходной декларации не понятно что декларарируется: или DobleValue с двумя одинаковыми элементами или что DobleValue должен проверить 2 однаковых аргумента. Это вобщем разные вещи.

хаскелевские tuple-ы вместе с кострукторами отображаютяс в структуры.

а поскольку работаем с типами

typecase
был бы уместнее. этож не велосипедная схема в конце-концов

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

> да. но поскольку в лиспе богатые возможности для ФП

Это mapcar даёт «богатые возможности для ФП» ? В чём заключаются эти богаты возможности?

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

> Чистота она относительна

Определение ФП в конце концов будет или нет? Зачем приводить все эти невразумительные объяснения, если было дано конректное определение и вся суть CL ему противоречит? Либо давайте другое определение ФП, либо тему уже давно исчерпана.

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

И вторая пара вопросов. Лисповский LOOP может быть чистым согласно твоему пониманию? Если да, то он может быть использован как элемент построения ф.п. кода?

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

Ну т.е. определния не будет? Общеизвестное широко распространённое определение мы отвергаем, но ничего другого не предлагаем? Так в чём логика?

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

О DEFTYPE и TYPECASE не знал. Спсб за наводку.

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

> Лисповский LOOP может быть чистым согласно твоему пониманию?

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

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

Общеизвестное определения а-ля википедия ни кто не отвергает. Отвергают твое определение ФЯП как языка с подстановочной моделью (грубо говоря, путаешь причину и следствие), а так же то, что ты утверждаешь, что CL не ФЯП, основывая это на вычислительной модели CL, что неверно в корне, и на том, что CL не предоставляет _удобных_ возможностей для ФП (в тему твоего поста, про GObject, ассемблер и проч.). Последнее может говорить только о том, что ты не писал достаточно на чистом как слеза хаскеле, чтобы понять, что никаких особенных удобств по сравнению с CL там нет.

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

>> Не понял.

Он хочет сказать про деструктивное присваивание переменным цикла :) Что кстати далеко не факт. В лиспе цикл - макрос, в отличие от. И он без проблем может развернуться в рекурсивные вызовы без деструкции данных.

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

> Он хочет сказать про деструктивное присваивание переменным цикла :)

Ну, тогда и хаскель «нарушает функциональную парадигму», ибо транслируется, о ужас, в императивные деструктивные машинные инструкции :)

Мне эта ситуация чем-то напоминает религиозного последователя, который буквально понимает все написанное в библии, коране или талмуде. Это нельзя, то не ешь, так не делай, LOOP и SETF не используй... Но религия выше этого и гораздо глубже.

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

Функциональщина - это более высокий уровень абстракции. Нам по барану какими методами она реализуется. Будь там внутри LOOP и SETF. Главное, что программа _вычисляет_ свой результат как функцию. Все.

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

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

Он хочет сказать про деструктивное присваивание переменным цикла :)

Нет, я не об этом, а вот о чём:

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

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

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

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

> Функциональщина - это более высокий уровень абстракции.

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

SETF. Главное, что программа _вычисляет_ свой результат как функцию.


Все.



«программа _вычисляет_ свой результат как функцию» противоречит loop и setf.

И в лиспе такие средства очень хороши и выразительны.


О каких средствах идёт речь? Можно перечислить?

В С++ есть STL, многие алгоритмы которой можно трактовать как функциональные. При этом, STL превосходит аналогичные средства Common Lisp для работы с последовательностями. А ещё не стоит забывать про boost::function и boost::lambda. С++ является ФЯП?

И ещё раз: является ли JavaScript ФЯП? Есть ли какое-либо преимущество у Common Lisp над JavaScript с точки зрения ФП? Я вот их не вижу..

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

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

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

Другой вопрос что называть вычислением. (format t «Hello, world») - это вычисление или нет? С точки зрения императивщины нет - это предписание, с точки зрение функциональщины - да, вычисление значения неявного параметра.

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

> Вот никогда мне не нравилось это определение.

Ну т.е. вы опять отвергаете широко известное свойство ФП? Так что же, в конце то концов, такое ФП в вашем понимании? Я просто теряюсь в догадках о чем вы всё время говорите.

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

> Ну, тогда и хаскель «нарушает функциональную парадигму», ибо транслируется, о ужас, в императивные деструктивные машинные инструкции :)

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

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

последовательность и пошаговость легко делаются и в функциональных языках

f (g (h(x))) - сначала вычислиться h, потом g, потом f - все, - последовательность и пошаговость есть. Главное отличие императивщины от функциональнщины - это разные вычислительные модели, и соответствующие их плюсы и минусы.

Функциональщина - это более высокий уровень абстракции.

Макросы, которые дают более высокий уровень абстракции, ты тоже к функциональщине запишешь?

Главное, что программа _вычисляет_ свой результат как функцию.

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

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

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

Это так определяется декларативное программирование. А то не ровен час и пролог к функциональщине припишем.

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

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

Откуда такая цитата? Функциональщине ближе не «как решить задачу», а «что решить». Тонкий момент. В этом плане пролог особенно хорошо прочищает мозги :)

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

А ты думай не о том, как loop реализуется лисп-системой. Думай о том, _что_ он делает. И тогда все встанет на свои места.

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

С++ является ФЯП?

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

Твоему упорству можно позавидовать :)

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

А то не ровен час и пролог к функциональщине припишем.

А ты в журнал fprog заглядываешь? ;)

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

>> Так что же, в конце то концов, такое ФП в вашем понимании?

Не более и не менее чем приведенное выше определение из википедии (использование функций в мат. смысле, без побочных эффектов, невных аргументов и пр.), все остальные критерии, приведенные тобой - частности, характеризующие тот или иной аспект ФП.

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

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

> Это так определяется декларативное программирование.

А то не ровен час и пролог к функциональщине припишем.


Функциональное программирование считается разновидностью декларативного, сюрприз?

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

primes = 2:[x | x <- [3, 5..], not $ any ((== 0).(mod x)) $ takeWhile (<= floor (sqrt $ fromIntegral x)) primes] Порядок вычислений тут важен. Где нарушение функциональной парадигмы?

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

> использование функций в мат. смысле, без побочных эффектов,

невных аргументов и пр.


В Common Lisp очень широко используются динамические переменные и что бы написать реальный код, не зависящий от них (а они выступают в роли неявных переменных) необходимо быть чрезвычайно осторожным (например, не использовать format и print). Да и вообще, что бы писать в ФП-стиле надо быть очень и очень осторожным и внимательным. Вот я и говорю, что Common Lisp не способствует написанию программ в ФП стиле, а наоборот, всячески этому препятствует. Так какой-же это ФЯП?

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

> Функциональное программирование считается разновидностью декларативного, сюрприз?

Но декларативное - это не только функциональное.

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

> Увы, не понимаю этот код и не могу его прокомментировать.

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

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

необходимо быть чрезвычайно осторожным (например, не использовать format и print)

Чтобы писать в функциональном стиле надо вообще забыть про ввод/вывод.

В Common Lisp очень широко используются динамические переменные

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

Вот я и говорю, что Common Lisp не способствует написанию программ в ФП стиле, а наоборот, всячески этому препятствует. Так какой-же это ФЯП?

(defun add (x y)
    (+ x y))

В чем препятствие?

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

Но декларативное - это не только функциональное.

Конечно, но значит в любом случае правильно утверждение, что

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

Там опять на тему, что последовательность вычислений

можно определять в чистых фп с помощью композиции функций.

Тогда всё нормально, никаких противоречий нет.

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

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

или так:

main = do putStrLn "What is 2 + 2?"
          x <- readLn
          if x == 4
              then putStrLn "You're right!"
              else putStrLn "You're wrong!"

Императивненько так получается )))

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

>> Спрятали страшные клубки монад и стрелок в do и радуются как дети :)

:)))

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

> Да мало ли что там используется. Абсолютно пофиг

во что транслируется текст функции


При чём здесь во что транслируется? Ладно, опустим ввод/вывод, как, например, прокомментируете роль динамических переменных *debugger-hook* и *break-on-signals*? Прошу обратить внимание, что вызов подавляющего большинство функций может при тех или иных условиях привести к появлению ошибки?

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

> Функциональщина - это более высокий уровень абстракции. Нам по барану какими методами она реализуется. Будь там внутри LOOP и SETF. Главное, что программа _вычисляет_ свой результат как функцию. Все.

Тогда вообще все программы функциональные, не?

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

>> При чём здесь во что транслируется?

Попробуй (macroexpand '(defun add (x y) (+ x y)))

прокомментируете роль динамических переменных *debugger-hook* и *break-on-signals*?

Ну да, не ФП подход к обработке ошибок. Это абсолютно не противречит тому, что на CL можно _легко_и_непринужденно_ писать в стиле ФП и иметь все прелести ФП (а она там по сути одна - program reasonning).

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

Может привести и что?

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

> Попробуй (macroexpand '(defun add (x y) (+ x y)))

И что я там должен увидеть?

на CL можно _легко_и_непринужденно_ писать в стиле ФП

Может привести и что?



А то что итоговое поведение системы зависит от неявных аргументов: *debuger-hook* и *break-on-singlas*. Только динамические переменные используются не только для ввода/вывода и обработки исключений, но вообще повсеместно, как в стандарте, так и в коде реализаций (каждая реализация добавляет своих), так и в пользовательском коде. Формы defparameter и defvar приводят к появлению динамических переменных. Любой вычислительный процесс в Common Lisp просто нашпигован неявными аргументами.

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

> Почему это?

Потому что там внутри LOOP и SETF, но программа _вычисляет_ свой результат как функция. Все программы (ну ладно, пусть большинство) вычисляют свой результат как функцию от входных данных.

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

> Конечно, но значит в любом случае правильно утверждение, что

неправильно. ты перепутал, «как решить задачу» — это как раз императивное описание, а декларативное (и функциональное) — это «что нужно получить». чтобы не перепутать, можно просто вспомнить какое-нибудь определение из математики, например:

корень n-й степени из x — это такой y, что y в степени n равно x

-- сугубо декларативное описание, которое говорит нам, что такое корень n-й степени, но совершенно не говорит какие действия (шаги) нужно совершить, чтобы получить значение y

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

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

Это не так (если, конечно, не считать текущее состояние системы одним из входных аргументов).

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

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

Это не так

Пример? Например, является ли конвейер ls | sort | uniq функциональной программой? А вызов (ls >t; sort <t >t1; uniq <t1 >t2)?

(если, конечно, не считать текущее состояние системы одним из входных аргументов).

Считать, конечно. Иначе откуда ты возьмешь входные данные для программы?

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