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
и его использование в хвостовом положении проверяется компилятором. (Специальные формы).