Clojure против других Lisps

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

Я прочитал несколько книг по Clojure (Программирование Clojure, Практический Clojure, Радость Clojure и версия Manning Early Access Clojure в действии), и я думаю, что это фантастический язык. В настоящее время я читаю Let Over Lambda, который в основном имеет дело с Common Lisp макросами, и это тоже очень интересный язык.

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

Преимущества Clojure (и недостатки "других" ):

  • Работает на JVM.

    • JVM - это очень стабильная, высокопроизводительная языковая среда, которая хорошо сочетается с мечтой Sun: "Напишите один раз, запустите [почти] в любом месте". Я могу написать код на моем Macbook Pro, скомпилировать его в исполняемый файл JAR, а затем запустить его в Linux и Microsoft Windows с небольшим дополнительным тестированием.

    • JVM (Hotspot и др.) поддерживает высококачественную сборку мусора и очень эффективную компиляцию и оптимизацию точно в срок. Где всего несколько лет назад я написал все, что нужно было быстро запускать на C, теперь я не стесняюсь делать это на Java.

    • Стандартная, простая, многопотоковая модель. Имеет ли Common Lisp стандартный многопоточный пакет?

    • Прерывает монотонность всех этих круглых скобок с [], {} и #{}, хотя эксперты Common Lisp, вероятно, скажут мне, что с помощью макросов-читателей вы можете добавить их в CL.

Недостатки Clojure:

  • Работает на JVM.
    • Нет рекурсии хвоста или продолжения. Поддерживает ли Common Lisp продолжение продолжения? Я считаю, что схема требует поддержки для обоих.

Преимущества других (общий Lisp, в частности) (и недостатки Clojure):

  • Определяемые пользователем макросы читателей.

  • Другие преимущества?

Мысли? Другие отличия?

Ответ 1

Мой личный список причин для предпочтения Clojure другим Lisps (p.s. Я все еще думаю, что все Lisps великолепны!):

  • Работает на JVM - следовательно, получает автоматический доступ к фантастической инженерии в самой JVM (расширенные алгоритмы сбора мусора, оптимизация JS HotSpot и т.д.).

  • Очень хорошая совместимость с Java - обеспечивает совместимость с огромным набором библиотек в языковой экосистеме Java/JVM. Я использовал Clojure в качестве "клеящего" языка для подключения различных библиотек Java с хорошим эффектом. Поскольку я также разрабатываю много кода Java, для меня полезно, что Clojure хорошо интегрируется с инструментами Java (например, я использую Maven, Eclipse с плагином против часовой стрелки для разработки Clojure)

  • Хороший синтаксис для векторов [1 2 3], отображает {:bob 10, :jane 15} и устанавливает #{"a" "b" "c"} - Я рассматриваю эти довольно важные инструменты для современного программирования (в дополнение к спискам, конечно!)

  • Мне лично нравится использование квадратных скобок для связывания форм: например, (defn foo [a b] (+ a b)) - Я думаю, что он делает код более понятным для чтения.

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

  • Отличная реализация STM для многоядерных concurrency. Я полагаю, что Clojure имеет лучшую историю concurrency любого языка на данный момент (см. Этот видео для большей разработки самим Ричем Хики)

  • Это a Lisp -1 (например, Scheme), который я лично предпочитаю (я думаю, что на функциональном языке имеет смысл хранить функции и данные в одном и том же пространстве имен)

Ответ 2

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

Общий Lisp определенно поддерживает функциональное программирование, но также позволяет изменять состояние и императивное программирование.

Конечно, существует ряд преимуществ для функционального программирования в области concurrency и в противном случае. Но при прочих равных условиях также хорошо иметь выбор того, какой подход вы хотите использовать для каждой ситуации. Clojure не полностью запрещает императивное программирование, но он менее приспособлен к этому стилю, чем Common Lisp.

Ответ 3

Имейте в виду, что Clojure - это язык и реализация (обычно на JVM). Common Lisp - это язык с более чем десяти различными реализациями. Итак, у нас есть несоответствие категории прямо здесь. Например, вы можете сравнить Clojure с SBCL.

В общем:

  • версия Common Lisp работает на JVM: ABCL

  • большинство других Common Lisp реализация не

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

  • Общий Lisp имеет синтаксис для массивов. Синтаксис для других типов данных может быть написан пользователем и предоставлен различными библиотеками.

  • Общие Lisp не поддерживают ни оптимизацию хвостовых вызовов, ни продолжения. Реализации обеспечивают TCO и библиотеки, которые предоставляют некоторые формы продолжений.

Ответ 4

Здесь хорошее видео с сравнение схемы (в основном, Racket) и Clojure.

Чтобы быть справедливым, Racket имеет синтаксический сахар (дополнительный материал для чтения) для типов данных тоже (#hash, #, квадратные скобки и т.д.)

Плюс, Clojure единственный способ сделать правильный хвостовой вызов - использовать recur, это недостаток компиляции в JVM.

Обратите внимание, что recur является единственной конструкцией цикла без использования стека в Clojure. Нет хвоста оптимизация и использование самозапуска для циклирования неизвестных границ не рекомендуется. recurи его использование в хвостовом положении проверяется компилятором. (Специальные формы).