LINUX.ORG.RU

Какой Lisp лучше в каких случаях и почему? И вообще в чём принципиальна разница между ними.

 , , ,


3

6

И есть ли такой диалект лиспа который бы был одинаков для всей этой необъятной кучи смайлоязыков. Ну и до кучи объясните мне, зачем диалекты вообще нужны, ну вот зачем? Когда общий синтаксис которого нет одинаков, а новые возможности это просто сахар с верху и ключевые слова которые просто как расширения или там библиотеки можно делать, но зачем делать по сути. Не холивара ради, просто интересно.

Сабж.

Deleted

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

гигиену к CL прикрутить невозможно

А зачем она там нужна? В скиме от неё много пользы? По мне так больше вреда. Абсолютно не читаемый бред получается, а в defmacro всё понятно и в 90% случаев даже macroepand не нужен что бы понять что к чему. Вот разработка в образе вполне себе практическая вещь. В особенности с таким отладчиком как в allegro CL. Кстати, известно что францы в своё время отказались от собственноuj lbfktrnf лиспа в пользу CL, потому что CL стал завоёвывать позиции в мире продакшена и сейчас францы от CL отказываться не спешат не смотря на отсутствие колл/сиси и прочей гигиеномути. Значит профессионалы в этом всём толка не видят, зато созданная вокруг Allegro инфраструктура (в т.ч. биндинг к ЖВМ, привет клоужуристам) делает CL не умирающим языком с полурабочими либами, как некоторые пытаются изобразить, а более чем годным инструментом для продакшена и тот факт, что он не стал попсой его даже красит. Ну а студенты пусть себя развлекаются написанием бейсиков. Это весьма забавна, кстати, что поклонники Ракетки считают достоинством оной возможность писать ДСЛи без с-выражений. Бгг! Как говорится напугали лиспера скобочками.

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

А зачем она там нужна? В скиме от неё много пользы?

Да. Нет проблем с возможными коллизиями имён в том месте, где макрос определяется и в том, где он используется.

Абсолютно не читаемый бред получается

Тебе

(define-syntax my-or
  (syntax-rules ()
    ((my-or) nil)
    ((my-or arg1) arg1)
    ((my-or arg1 args ...) (let ((temp arg1))
                              (if temp 
                                  temp 
                                  (my-or args ...))))))
читается сложнее, чем
(defmacro my-or (&rest args)
  (cond
    ((null args) nil)
    ((null (cdr args)) (car args))
    (t (let ((temp (gensym)))
         `(let ((,temp ,(car args)))
            (if ,temp
                ,temp
                (my-or ,@(cdr args))))))))
?

и в 90% случаев даже macroepand не нужен что бы понять что к чему

Я макросы Racket практически в 100% случаев читаю не прибегая к expand.

Это весьма забавна, кстати, что поклонники Ракетки считают достоинством оной возможность писать ДСЛи без с-выражений.

Поклонники Ракетки считают достоинством наличие любой возможности. Если она не нужна, не используй, но если она нужна, то лучше когда она есть. Поэтому в Ракетке в отличие от CL есть финализаторы (которые выполняются перед удаление объекта), эфемероны, call/cc, call-with-escape-comntinuation, call-with-composable-continuation, call-with-continuation-barrier, security guard, inspector, custodian, impersonator, chaperon, typed racket и модули.

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

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

То есть они честно признались, что гигиену к CL прикрутить невозможно.

Разве? А я вижу что они описали аж два способа как пофиксить эту проблему. Это значит признались что невозможно?

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

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

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

Гомоиконность уже ограничивает расширяемость. Запрещены любые негомоиконные синтаксисы.

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

Правильная расширяемость у Racket

Правильная по твоему личному определению правильности? Если так, то правильная у Red/REBOL, а Racket для детей.

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

Поклонники Ракетки считают достоинством наличие любой возможности. Если она не нужна, не используй, но если она нужна, то лучше когда она есть.

Это же идеология C++, нет?

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

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

Для моих примеров не приходится менять ядро компилятора. Поэтому с моей точки зрения компилятор должен поддерживать максимально возможное количество примитивов. А парсер в перспективе можно приделать любой.

От того насколько глубоко в конкретную реализацию встроены те или иные фичи зависит настолько сложно будет их менять, это как бы очевидно.

А зачем их менять? Вот у CL в фичах сборщик мусора, динамические переменные, символы. Много было библиотек с альтернативными реализаций?

А я вижу что они описали аж два способа как пофиксить эту проблему. Это значит признались что невозможно?

Да. Первый способ: назовите как-нибудь и надейтесь, что не пересечётся. Второй способ: вручную переберите все используемые объекты и укажите их в with.

Постановка задачи гигиены «все объекты макроса, не являющиеся параметрами, определяются по месту описания макроса» явно не решена.

Это всё равно что решение проблемы отсутствия сборщика мусора в C++:

  • не забывайте для каждого new делать delete
  • используйте смарт-пойнтеры в простых случаях

.

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

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

Это звучит как «покажи проблему, которую нельзя решить на машине Тьюринга».

Хорошо. Напиши гомоиконным синтаксисом пример из Rust

pub fn wraps<T: Serialize>(e: T) -> Result<Context, RenderError> {
    to_value(e)
        .map_err(RenderError::from)
        .map(|d| Context { data: d })
}

Правильная по твоему личному определению правильности?

По критерию максимальных возможностей.

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

Это же идеология C++, нет?

Ты так говоришь, словно это что-то плохое. Кстати, есть макросы Racket + производительность C++. Называется L++.

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

Поклонники Ракетки считают достоинством наличие любой возможности. Если она не нужна, не используй, но если она нужна, то лучше когда она есть.

И при этом в Ракете нет дебагера и нормального программирования образа?

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

И при этом в Ракете нет дебагера и нормального программирования образа?

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

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

Очень похоже на macro-by-example из Rust.

В данном случае Nemerle, но Rust тоже не хуже выглядит.

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

Да. Нет проблем с возможными коллизиями имён в том месте, где макрос определяется и в том, где он используется.

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

читается сложнее, чем

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

Я макросы Racket практически в 100% случаев читаю не прибегая к expand.

Поздравляю! Надеюсь речь идёт не о макросах вроде my-end, my-when и т.п., т.е. из учебной литературы.

Но вот, например, такую функцию взять

(define max-mag (lambda (num . nums) (apply max (map magnitude (cons num nums)))))

Вопрос, зачем тут эта lambda, если всего-то остаточный аргумент надо задать и не проще ли обычный &rest? Пусть мелочь, но из мелочей всё складывается.

Поклонники Ракетки считают достоинством наличие любой возможности.

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

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

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

Как это не приходится, на ракете можно реализовать `unwind-protect` без изменения ядра компилятора?

А зачем их менять?

Ну так ты у себя это спрашивай, твои примеры были про гигиенические макросы и call/cc.

Постановка задачи гигиены «все объекты макроса, не являющиеся параметрами, определяются по месту описания макроса» явно не решена.

Все объекты макроса _использующие данную реализацию_ будут гигиеническими, что как бы и есть решение.

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

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

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

Ну, на самом деле это я и имел в виду. Хотя забыл, что «телепаты в отпуске».

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

Вопрос, зачем тут эта lambda, если всего-то остаточный аргумент надо задать и не проще ли обычный &rest? Пусть мелочь, но из мелочей всё складывается.

Вместо &rest там точка. Можно просто написать

(define (max-mag num . nums) (apply max (map magnitude (cons num nums))))

И не нужно никаких &rest. А определение функций через (define max-mag ...) позволяет писать

(define max-mag (map-reduce magnitude max))
А на CL приходится многословить
(defun max-mag (&rest rest) (apply (map-reduce magnitude max) rest))
или сохранять в переменную, а потом каждый вызов заворачивать в funcall.

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

Особой разницы нет, натыкаешься на использование какой-нибудь возможности, которую не используешь или какой-нибудь библиотеки, которую не используешь. Например, это тоже CL: https://hub.darcs.net/hu.dwim/hu.dwim.presentation/browse/source/component-hi...

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

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

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

Как это не приходится, на ракете можно реализовать `unwind-protect` без изменения ядра компилятора?

Он называется dynamic-wind.

Ну так ты у себя это спрашивай, твои примеры были про гигиенические макросы и call/cc.

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

_использующие данную реализацию_

Тогда придётся либо использовать только функции из CL, либо писать что-то вроде

(defun (f-let-if f1 f2)
  (let ((temp (f1))
    (if temp temp (f2))))

(defmacro my-or (&rest args)
  (cond
    ((null args) nil)
    ((null (cdr args)) (car args))
    (t (let ((f-let-if #'f-let-if))
      `(funcall ,f-let-if 
                (lambda () ,(car args))
                (lambda () (my-or ,@(cdr args)))))))
Вот единственный вариант гарантировать, что переопределение символов из тела макроса не поломает макрос. Если раскрывается в другой макрос, то вообще придётся вручную макроэкспанд вызывать.

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

Там DSL на уровень выше макросов.

Только не компилируется.

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

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

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

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

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

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

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

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

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

Потом спрашивают, зачем Хикки навелосипедил Clojure.

асинхронность

Господи, в Racket и то осилили. Хотя графика да, тоже через ffi.

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

Лучше чем другой лисп для тех или иных задач. То есть чем scheme лучше common lisp для ... и ... потому что ... . Про другие языки речи нет, только про «семейство» лиспов. Я вот хочу что бы можно было интерпретировать/компилировать/встраивать + минималистичный дизайн языка + строгость. Биндинги к С для возможности использовать в качестве «системного» или расширять функционал за счёт библиотек, а не встроенных в язык «фишек» то есть хочу я треды то я pthread прикручу и всё. Сейчас смотрю на scheme, пока не могу выбрать книженцию где по делу и стандарту и реализацию где по стандарту и кроссплатформенно, вроде guile под всё подходит. Пока что мне не для серьёзного, а что бы мозг встряхнуть от окупации Си. Он не куда не денется я люблю Си, но всё больше хочется какой-то язык «напарник» (полноправный,а не спутник) который будет красив, лаконичен, надёжен, строг. Но покрывающий те задачи где не всегда удобен С, а так же для прототипирования чего либо. Выбор пал на «семейство» лиспов, но жизнь одна я гляну то на всё подряд, а вот уже вникать поглубже меня хватит только в один какой нибудь, по ряду многих причин включая физические. Гы ::) А пока читаю дискуссии и матаю на ус что тут обсуждают.

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

Я вот хочу что бы можно было интерпретировать/компилировать/встраивать + минималистичный дизайн языка + строгость.

Если встраивать, то реально только guile или chibi. Из CL'ов встраивается только ECL, но он, насколько я помню, даже стандарт ANSI не полностью поддерживает.

а не встроенных в язык «фишек» то есть хочу я треды то я pthread прикручу и всё

Сборщик мусора обязан знать про потоки. Так что если не встроен, то не прикрутишь.

Сейчас смотрю на scheme, пока не могу выбрать книженцию где по делу и стандарту

Классика http://newstar.rinet.ru/~goga/sicp/sicp.pdf

и реализацию где по стандарту и кроссплатформенно, вроде guile под всё подходит

Он только R5RS и кусок R6RS реализует. Chibi реализует R7RS small.

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

По крайней мере есть стандартные и переносимые racket/draw и racket/gui.

И чем они стандартны? ))) Тем что PLT Scheme aka DrRacket — это единственная реализация этого якобы стандарта? ))))

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

Описание и обработка связной логики, состояний, событий, таймеров, обработка (не знаю как называется) когда значение A зависит от B и если изменилось A меняется и B но в случае если B достигло какого либо предела то меняется С, типа триггеры или что-то типа того. Обработка текста.

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

Кстати, в том же Allegro CL Гуй можно набрасывать за пару секунд визуально на лету.Сейчас Монк конечно же вспомнит, что в ПЛТ Ракет тоже было нечто подобное. Я говорю «было» потому что эту жесть кажется окончательно забросили, и слава богу, потому что была она абсолютно не юзабельна, легче пальчиками было накидать её богу. Это к слову о полурабочих либах. Не всё то немногое, что написано в Ракете идеально работает, я вот сейчас просматриваю список пакетов отмечены красным и жёлтым. Зачем их держат в репозитории? Видимо для солидности! Правда я тут присмотрелся к названиям некоторых из них... Например, есть такой как tetris, наверняка что-то очень важное для Ракет--сообщества, правда отмечено красной пометкой — faild, но думаю в ближайшее время баги пофиксят.

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

Спасиб, ну значит хотелки придётся поубавить. Главное что бы от них хоть что-то осталось по итогу, а то всё сведётся просто к временному интересу ))

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

Ну с таким-то подходом любой лисп противопоказан.

Глупость какая! Если ты намекаешь на ДСЛи, то будучи написаны хорошо они все имеют декларативную семантику и тому тем паче способствовать должны с-выражения. Поэтому то и глупо писать на лиспе ДСЛ без скобочек, да ещё этим гордиться. Впрочем для студентов пойдёт, потому как понятно, что любая сокурсница потечёт и даже даст, если показать что вот смотри чо могу: было со скобочками, а потом «бац» и без скобочек. Только практический смысл этого скобочного геноцида в чём? Усложнить себе жизнь? Хорошо, когда ты написал что-то с заранее известным синтаксисом, типа паскаля (тут Вирт определённо должен захлопать в ладоши), а если нет? Не лучше ли сохранить для созданного ДСЛя основное преимущество Лиспа? Простой синтаксис основанный на с-выражениях?

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

И чем они стандартны? ))) Тем что PLT Scheme aka DrRacket — это единственная реализация этого якобы стандарта? ))))

Тем, что почти весь графический софт под Racket использует эти библиотеки и стабильно работает на любой ОС (Win/Mac/Linux), а не как в CL: полтора десятка библиотек, из которых половина уже не работает, а оставшиеся недоделаны.

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

Я говорю «было» потому что эту жесть кажется окончательно забросили, и слава богу, потому что была она абсолютно не юзабельна, легче пальчиками было накидать её богу. Это к слову о полурабочих либах.

Она не в составе Racket была, а в Planet.

Не всё то немногое, что написано в Ракете идеально работает, я вот сейчас просматриваю список пакетов отмечены красным и жёлтым. Зачем их держат в репозитории?

В репозитарии держат всё. В Racket входит только то, что входит в дистрибутив: в списке пакетов фильтруй по main-distribution.

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

Тем, что почти весь графический софт под Racket использует эти библиотеки и стабильно работает на любой ОС (Win/Mac/Linux), а не как в CL: полтора десятка библиотек, из которых половина уже не работает, а оставшиеся недоделаны.

CAPI в LW и Allegro CL interface to GTK не работают и не доделаны? ))) А почему я тогда накидываю в Allegro виджеты на формочку и всё работает? )))

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

Поэтому то и глупо писать на лиспе ДСЛ без скобочек, да ещё этим гордиться

Зависит от сложности ДСЛ. Если примитивный, то всё равно. А если надо изобразить что-то хотя бы вроде перловых регулярок, то скобочный вариант будет выглядеть ужасно.

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

CAPI в LW

А на нём хоть одну программу кроме самого LW написали? Выглядит он как привет от Win95.

Allegro CL interface to GTK

Судя по описанию в ACL 10.1, они в 2017 году поддерживают только GTK1 и GTK2... список поддерживаемых ОС тоже «радует». FreeBSD 9.3, вышедшая в 2014 и для Linux/x86-64 glibc 2.12.

Даже бесплатный Racket давно поддерживает GTK3.

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

Не я хотел типа

(define a 1)
(define b 2)
(define c 1)
(register-depends-inc a b 1);; a зависит от b если b изменилось a инкрементируется на еденицу автоматом
(register-depends-dec c b 1);; с зависит от b но уменьшается если изменилось b
(set! b 1) ;; задаём новое значение (и тут магически где то как то меняются a и с) ну или через (register-depends-update) какой нибудь
(display a b c) ;; вывод 2 1 0 

;; тоже самое для событий тоесть есть разные эвенты
;; двинул мышкой эвент, тыкнул мышкой эвент (как пример)
;; тоесть мы регистрируем эвенты и зависимости друг от друга
;; если случилось A  то вызвать B  и так далее как каскад
;; или более живой пример у меня происходит загрузка чего либо
;; и у меня есть окно говорящее "всё аебок я грузнулозь нормально" 
;; я диалоговое это окно просто описываю и всё, затем регистрирую эвент окончания загрузки на вывод окна с сообщением
;; так же как и пример выше и всё мне не надо париться и описывать логику оно само  обработает, ну вот как то так

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

Чувак бабок заплатил за Аллегро, вот его и бомбит. Ракетка и gtk4 начнёт поддерживать, вскоре как последний релизнут.

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

Реактивное программирование 🚀, точно,спасибо! Хотя от всей этой реактивности мне нужна только «каскадная» обработка данных/событий/состояний/процедур. Если это в целом тоже можно обозвать реактивностью то значит просто именно оно.

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

Он называется dynamic-wind.

http://www.nhplace.com/kent/PFAQ/unwind-protect-vs-continuations-original.html

А Питман говорит что не называется.

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

Я не говорю что должна быть альтернатива, или лучше. Я говорю что это разные вещи, если сильно надо - реализовать можно, если не надо то и проблем нет. При чем тут лучше или хуже.

Тогда придётся либо использовать только функции из CL

Непонял, почему это?

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