LINUX.ORG.RU
ФорумTalks

Более лучший Лисп

 


3

9

Что бы вы изменили и каким образом в своем любимом/нелюбимом диалекте Лиспа, чтобы он стал ещё лучше? Расскажите обо всех своих грязных фантазиях.

Лиспосрач (и те два унылых анонимуса) не приветствуется.

Перемещено tazhate из development

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

Статическая типизация - это смерть прототипирования, а успех проекта...

Мне как бы тоже больше статическая типизация нравится, но готов своё мнение пересмотреть.

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

Тогда в чем дело?

А ещё забавен аргумент про покрытие тестами. Для быстрого написания прототипов, ага. Указать типы у нас нет времени, а писать тесты нас не замедляет что ли?

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

Статическая типизация - это смерть прототипирования,

То-то так борзо прототипы наговнякиваются на хаскелле или ML-е.

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

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

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

Например, мы говорим, что продолжения могут быть только внутри with-call/cc и/или defun/cc.

Ничего, что код внутри будет полностью несовместим с кодом снаружи?

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

Неужели указание типов настолько сильно тормозит разработку?

Нет. Даже тупая типизация уровня Си экономит время.

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

Нет. Даже тупая типизация уровня Си экономит время.

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

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

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

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

Просто при написании прототипов недостатки динамики меньше заметны.

И если у лисперов есть репл

REPL есть много где - Python, Haskell, Scala.

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

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

Дело не в указании типов, а в распределении ответственностей выделении под них интерфейсов и абстрактных классов, фабрики, фабрики, фабрики. Пусть в IDEA это получается делать на лету, не отходя от кассы, но всё равно раздражает и рвет контекст.

// Это всё про жабку. На нормальных статически типизируемых языках не писал.

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

наговнякиваются на хаскелле или ML-е.

Это если прототип в систему типов укладывается.

А функцию типа

(defun safe-proceed (func)
  (ignore-errors (return-from safe-proceed (funcall func)))
  :fail)

попробуй сделать.

Или список с элементами разных типов. В общем, пока на грабли не наступишь, всё красиво, а как наступишь, так вместо написания алгоритма начинается нудное объяснение компилятору, чего от него надо.

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

добавил бы в sbcl возможность делать готовые бинарные пакеты со всеми зависимостями

(save-lisp-and-die :executable t) не то?

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

Очень нужна, с нормальным тайпинференсом

А чего тебе не ватает в SBCL-ном инференсе?

> (defun test (x y) (list (+ x y) (length x)))
; in: DEFUN TEST
;     (LENGTH X)
; 
; caught WARNING:
;   Derived type of X is
;     (VALUES NUMBER &OPTIONAL),
;   conflicting with its asserted type
;     SEQUENCE.
monk ★★★★★
()
Ответ на: комментарий от naryl

Песочницы.

https://github.com/treep/sb-sandbox

Рекурсивные типы. Например, (deftype list-of (item) `(cons ,item (list-of ,item))

Тип бесконечной последовательности проверяемый бесконечное время? А зачем?

Вообще-то, для нормальных случаев satisfies достаточно.

Специальные функции. Т.е. функции с динамической областью видимости.

Так они такие и есть (кроме flet/labels). Меняешь fdefinition, запускаешь функцию, внутри неё виден изменённый fdefinition. Или в смысле?

Стандартный кроссплатформенный гуй.

https://github.com/jmorrison/mcclim

Стандартизация универсальных расширений вроде сокетов и потоков.

http://gitorious.org/iolib/iolib http://common-lisp.net/project/bordeaux-threads/

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

https://github.com/treep/sb-sandbox

Спасибо, посмотрю.

Специальные функции.

При наличии нескольких потоков все манипуляции с fdefinition ломаются.

https://github.com/jmorrison/mcclim

Так вот он где теперь. :) Надо под оффтопиком попробовать. Спасибо.

http://gitorious.org/iolib/iolib

Странно, где раньше спрашивал почему-то все советовали usocket. А ещё есть sb-bsd-sockets, реализованные в sbcl и ecl и которые оборачиваются usocket. Почти как с аудиосистемами в линуксе, только явных преимуществ друг перед другом у них нет.

http://common-lisp.net/project/bordeaux-threads/

Где стандарт? Хотя бы неформальный, но отдельный от реализации. Т.к. если стандарта нет, то интерфейс и поведение будут ломаться. Прецеденты с bordeaux-threads были.

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

Такое даже на жабе не сложно сделать (надо-то всего 15 минут времени и пару раз в документацию заглянуть):

  public static class SafeProceederResult<RetType> {

    public final RetType result;
    public final boolean failed;
    public final Exception cause; 

    public SafeProceederResult(Exception cause) {
      result = null;
      failed = true;
      this.cause = cause;
    }

    public SafeProceederResult(RetType result) {
      this.result = result;
      failed = false;
    }

    public static RetType proceed(Callable<RetType> c) {
      try {      
        return new SafeProceederResult<RetType>(c.call());
      } catch (Exception e) {
        return new SafeProceederResult<RetType>();
      }
    }
  }

Хыыыыы

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

Такое даже на жабе не сложно сделать

В catch, наверное, return new SafeProceederResult<RetType>(e)

А оно вообще работает?

В смысле

(defun complex-func-return-integer ()
  ...)

(setf x (+ 10 (safe-proceed (complex-func-return-integer))))

Боюсь на Java

public static int complex_func();

x = 10 + SafeProceederResult(complex_func);

будет громко ругаться. Или нет? proceed ведь вернёт не тот тип, который возвращает result?

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

Уточнение, с точки зрения того, что (safe-proceed (complex-func-return-integer)) должно иметь тип (or (member :fail) integer):

(defun complex-func-return-integer ()
  ...)

(let ((x (safe-proceed (complex-func-return-integer)))
  (if (eq x :fail) (proceed-fail) (+ x 10))

Это с точки зрения типов и статического анализа абсолютно корректно. Но ни в Java ни в Haskell union типов как таковых нет.

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

При наличии нескольких потоков все манипуляции с fdefinition ломаются.

То есть хочется на просто динамические, но ещё и с (let ...). А чем в таком раскладе

(let ((*handler* (lambda ...))) ...)

не устраивает? Я просто use-case пытаюсь понять.

Странно, где раньше спрашивал почему-то все советовали usocket. А ещё есть sb-bsd-sockets

USocket — старый стандарт

iolib — новый — быстрее работает, больше возможностей.

Примерно, как UFFI и CFFI.

SB-..., очевидно, реализация от SBCL

Где стандарт? Хотя бы неформальный, но отдельный от реализации.

http://trac.common-lisp.net/bordeaux-threads/wiki/ApiDocumentation

5 лет уже фиксирован, если не считать опечатки join-thread/thread-join

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

iolib — новый — быстрее работает, больше возможностей.

больше возможностей

Только для SBCL, так что не катит.

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

Как минимум, SBCL, CMUCL, Clisp, Clozure (http://common-lisp.net/project/iolib/)

Не спорю, iolib хороша, но нужна полная поддержка коммерческих лиспов (опять же реализуемо, было бы желание и время) + только для posix систем. usocket более «кросс-платформенен».

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

usocket более «кросс-платформенен».

Если нужны только сокеты, согласен, лучше usocket

Если нужен epoll или kqueue, то только iolib

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

REPL есть много где - Python, Haskell, Scala.

Про питон не скажу - использовал всего раз, да и давно это было.

Начнем со Scala. В maven и sbt есть возможность загрузить консоль, т.е. фактически REPL. Называется или scala:console или как-то так. Уже не помню точно. Тут две проблемы: (1) по большому счету после изменения кода нужно загружать все по новой в отличие от лиспа; (2) почему-то мне не удалось запустить эту консоль для проектов maven, разбитых на модули, и, честно говоря, я сильно не разбирался с этим. В итоге я просто забил на REPL при разработке на Scala. Ничего подобного лиспу не нашел. Так, только чтобы проверить небольшие конструкции.

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

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

(let ((*handler* (lambda ...))) ...)

use-case... Динамически патчить библиотечные функции. :) Чтобы моя версия имела динамическую область видимости и была локальной для потока.

SB-..., очевидно, реализация от SBCL

Которая есть уже не только в SBCL. Но в данном случае для меня вообще ускользает смысл обёрток.

Где стандарт? Хотя бы неформальный, но отдельный от реализации.

http://trac.common-lisp.net/bordeaux-threads/wiki/ApiDocumentation

Хорошо, если есть фиксированный стандарт (в котором пять лет не могут исправить «опечатку» :D), то почему его ещё никто не реализовал? В каждой лисп-системе свой API, который не использует *никто*, кроме bordeaux-threads.

За стандарт я приму только (хотя бы) CDR, но не доку с оф. сайта библиотечки-обёртки.

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

В смысле
(defun complex-func-return-integer ()
...)

(setf x (+ 10 (safe-proceed (complex-func-return-integer))))

Тут тоже ничего хорошего не будет, т.к. (+ 10 :fail) это в любом случае не то, что нужно.

public static int complex_func();
x = 10 + SafeProceederResult(complex_func);

В джаве конечно же все будет не так просто: SafeProceederResult<Integer> r = SafeProceederResult<Integer>.proceed(new Callable<Integer>(){ public Integer call() { // Это тело complex-func-return-intger } }); int x = 10 + r.failed? 0 : r.result;

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

Использую в практике. Сейчас пишем очень большой проект под Tcl/Tk. Клиент-серверное приложение, достаточно сложное, предположительно под конец разработки будет более 40 000 строк только у клиента. Ну и так, для себя, по мелочи пишу.

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

Вот только эффективного компилятора в Tcl не сделали. И не сделают.

Правда, для его области применимости (гуйня и мелкие скрипты) этого и не надо. У лиспа же вообще совершенно иная целевая аудитория, с tcl-ом не пересекающаяся.

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

Сейчас пишем очень большой проект под Tcl/Tk

Если бы ещё tk не был такой страшный... хотя в гугле обнаружил tcl/gtk.

monk ★★★★★
()

1. Убрал бы макросы. Совсем. Даже гигиену бы не оставил.

2. Убрал бы лямбды и замыкания. Совсем.

3. Разделил бы expressions и statements.

4. Добавил бы статическую типизацию и ООП в стиле Java.

5. Модули и пространства имен.

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

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

SafeProceederResult<Integer> r = SafeProceederResult<Integer>.proceed(

Здесь типы просто очень многословные. При хорошей IDE дают плюс, при кодинге в vim/emacs превращаются в издевательство.

А к Haskell и подобным претензия в том, что типы нормально обрабатываются только простые: целое число, строка, ....

Уже для простейшего (or integer string) приходится городить огород. Хотя SBCL с задачей инференса в таких ситуациях справляется.

Ну и мелочи типа невозможности сделать функцию с произвольным числом параметров (или параметром-списком из значений произвольных типов)

Или что-то типа

(defun g+ (a b)
  (typecase a
    (string (string+ a b))
    (number (typecase b 
              (number (+ a b)) (t (string+ a (string b))))))
    (t (string+ (string a) (string b)))))
monk ★★★★★
()
Ответ на: комментарий от monk

При хорошей IDE дают плюс, при кодинге в vim/emacs превращаются в издевательство.

Спрашивается, накойхер пользоваться vim или emacs, когда есть хорошие IDE?

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

А темы не пробовали использовать (ttk) ? Если с ними, то вообще все очень даже хорошо выглядит

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

Спрашивается, накойхер пользоваться vim или emacs, когда есть хорошие IDE?

патамуштоудобнее

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

Ничего подобного лиспу не нашел.

Ну, после «общелисп по-прежнему почти впереди планеты всей» это было понятно.

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

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

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

1. Убрал бы макросы. Совсем. Даже гигиену бы не оставил.

И что тогда останется от языка? Без макросов 90% «стандартной библиотеки» не будет работать...

2. Убрал бы лямбды и замыкания. Совсем.

А чем не устроили лямбды и замыкания? Неосилили ФП в целом или конкретно ФП в лишпах?

4. Добавил бы статическую типизацию и ООП в стиле Java.

И убили бы всю красоту лишпа...

5. Модули и пространства имен.

В какой реализации этого нет? Или про специфическую реализацию?

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

Как такового синтаксиса нет. Разве что блоки кода выделяются скобками.

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

Здесь типы просто очень многословные. При хорошей IDE дают плюс, при кодинге в vim/emacs превращаются в издевательство.

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

public class SomeClass<SomeType> {

  public final Class<SomeType> cls;

  public SomeClass(Class<SomeType> cls) {
    this.cls = cls;
  }

}

public class SomeSpecialClass extends SomeClass<SpecialClass> {
  public SomeSpecialClass() {
    super(SpecialClass.class);
  }
}

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

Неужели? А он нужен (компилятор tcl)? Да и как же тот же Eagle или Hecl?

Tcl по скорости сливает даже Perl'у, как его можно сравнивать с CL в принципе? Совсем разные области применения получаются.

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

И что тогда останется от языка? Без макросов 90% «стандартной библиотеки» не будет работать...

Стандартную библиотеку можно и переписать.

А чем не устроили лямбды и замыкания? Неосилили ФП в целом или конкретно ФП в лишпах?

ФП я осилил. Так что я против ФП принципиально и сознательно. ФП не должно быть. Его надо давить и истреблять везде, куда оно проникло.

И убили бы всю красоту лишпа...

Намекаю - в Java есть и опциональная динамическая типизация.

В какой реализации этого нет? Или про специфическую реализацию?

А где есть вменяемые пространства имен? Хочу, чтоб было как в Java.

Как такового синтаксиса нет.

И это хорошо. Это единственное, что в лиспе хорошо. Все остальное - плохо.

Короче, я хочу Java, но с синтаксисом Лиспа.

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

Согласен, я тоже не вижу смысла в Лисп-2, Лисп-1 вполне себе ок и вызывает меньше непонимания у новичков

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

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

Короче, я хочу Java, но с синтаксисом Лиспа.

По твоим критeриям из списка больше подходит Clojure.

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

Kawa можно пользоваться без какой бы то ни было связи с Java?

до первого стектрейса. Зачем джава если ей не пользоваться?

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

Короче, я хочу Java, но с синтаксисом Лиспа.

Зачем?

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

а продолжения не нужны

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

Можно как в других языках, но продолжения вроде более естественны

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

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

Вы может имели ввиду наоборот Лисп-1 (a b c) более стройный нежели Лисп-2 (funcall (function a) b c)?

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