Клоджуре проти інших Лісп [закрито]


93

Мета мого запитання - не розпочати полум'яну війну, а скоріше визначити, за яких обставин кожна мова є "найкращим інструментом для роботи".

Я прочитав кілька книг про Clojure ( Programming Clojure , Practical Clojure , The Joy of Clojure та Manning Early Access edition of Clojure in Action ), і я думаю, що це фантастична мова. Зараз я читаю Let Over Lambda, який здебільшого стосується макросів Common Lisp, і це теж дуже цікава мова.

Я не фахівець Lisp (більше новачок), але ця родина мов мене зачаровує, як і функціональне програмування загалом.

Переваги Clojure (і недоліки "інших"):

  • Працює на JVM.

    • JVM - це дуже стабільне, високопродуктивне мовне середовище, яке досить добре відповідає мріям Sun про "Пиши один раз, біжи [майже] де завгодно". Я можу написати код на своєму Macbook Pro, скомпілювати його у виконуваний файл JAR, а потім запустити на Linux та Microsoft Windows, не вимагаючи додаткового тестування.

    • (Hotspot та інші) JVM підтримує якісний збір сміття та дуже ефективну своєчасну компіляцію та оптимізацію. Де кілька років тому я писав усе, що мало швидко працювати на мові C, тепер я не соромлюсь зробити це на Java.

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

    • Перерви одноманітності всіх цих дужок з [], {}і #{}, хоча експерти Common Lisp, ймовірно , сказати мені , що з читанням макросами, ви можете додати їх до CL.

Недоліки Clojure :

  • Працює на JVM.
    • Відсутність рекурсії хвоста або продовжень. Чи підтримує Common Lisp продовження? Я вважаю, що схема вимагає підтримки обох.

Переваги інших (зокрема, Common Lisp) (та недоліки Clojure):

  • Встановлювані користувачем макроси.

  • Інші переваги?

Думки? Інші відмінності?


15
особисто мені подобається один вид дужок;) виглядає як "чистіший" код
Мо

3
З того, що я прочитав у вашому списку переваг, я думаю, вам може також сподобатися Erlang www.erlang.org
Peer Stritzinger

4
Clojure підтримує явну рекурсію хвоста за допомогою спеціальної форми "repeat". Це дозволяє отримати всі переваги рекурсії хвоста за умови прямого прохання про це (єдиним винятком є ​​те, що в даний час вона не підтримує взаємні рекурсії хвоста між кількома функціями).
mikera

1
Clojure також підтримує продовження, принаймні в сенсі "стилю передачі продовження". Ви праві, що він не має першокласних продовжень. см stackoverflow.com/questions/1173133/continuations-in-clojure
mikera

@mikera: рекурсія хвоста на одній функції. Дві функції, що викликають одна одну, повинні виконуватися за допомогою "стрибків на батуті", що є якось по-класному (але по-своєму елегантно :-)).
Ральф,

Відповіді:


52

Мій особистий список причин віддавати перевагу Clojure перед іншими Lisps (ps, я все ще вважаю, що всі Lisps чудові!):

  • Працює на JVM - отже, отримує автоматичний доступ до фантастичної інженерії в самій JVM (вдосконалені алгоритми збору сміття, оптимізація HotSpot JIT тощо)

  • Дуже хороша сумісність 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 для багатоядерного паралелізму. Я вважаю, що на даний момент у Clojure найкраща історія паралелізму з будь-якої мови (див. Це відео для детальнішої розробки самого Річа Хікі )

  • Це Lisp-1 (наприклад, схема), який я особисто віддаю перевагу (я думаю, що у функціональній мові має сенс зберігати функції та дані в одному просторі імен)


2
+1 для STM. За допомогою itselft достатньо, щоб виправдати використання Clojure.
Андре Карон,

2
Ви все ще можете отримати STM за допомогою бібліотеки CL-STM.
Mike Manilone

2
@ AndréCaron, лише якщо вам це потрібно.
праворуч

Якщо ви хотіли написати простий веб-додаток і розмістити його, скажімо, на дешевому хості за 5 доларів на місяць, це, очевидно, неможливо з Clojure через JVM, правильно?
Hexatonic

@Hexatonic Я не дуже досвідчений, але важко повірити, що машина, що використовується сьогодні, не матиме JVM.
MasterMastic

25

Майте на увазі, що Clojure - це мова та реалізація (як правило, на JVM). Common Lisp - це мова з більш ніж десятьма різними реалізаціями. Отже, тут ми маємо невідповідність категорій. Наприклад, ви можете порівняти Clojure із SBCL.

Загалом:

  • версія Common Lisp працює на JVM: ABCL

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

  • більшість реалізацій CL мають багатозадачність, бібліотека забезпечує загальний інтерфейс

  • Common Lisp має синтаксис для масивів. Синтаксис для інших типів даних може бути написаний користувачем і надається різними бібліотеками.

  • Common Lisp не підтримує ні оптимізацію хвостових викликів, ні продовження. Реалізації забезпечують TCO, а бібліотеки забезпечують певну форму продовження.


24

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

Common Lisp однозначно підтримує функціональне програмування, але він також дозволяє змінювати стан та імперативне програмування.

Звичайно, функціональне програмування має низку переваг, як в області паралельності, так і в інших випадках. Але за інших рівних умов також добре мати вибір, який підхід ви хочете використовувати для кожної ситуації. Clojure не повністю забороняє імперативне програмування, але він менш пристосований до цього стилю, ніж Common Lisp.


3
@Charlie Flowers: Я вважаю, що в Common Lisp можна програмувати в "чисто функціональному" стилі (стійка підтримка структури даних тощо), але вимагає дисципліни. Правильно?
Ральф,

2
Просто роз'яснення щодо "відсутність побічних ефектів, відсутність змінних станів" - Clojure має змінний стан (посилання, атоми, агенти тощо змінюються), але вимагає, щоб ви отримували доступ до нього контрольовано (тобто через механізми STM та відповідні транзакції оновити семантику)
mikera

5
@mikera: за винятком того, що Clojure покладається на використання бібліотек Java, щоб бути придатною для використання, і всі ці бібліотеки вимагають імперативного стилю і повні побічних ефектів. Я знайшов прив'язки до Java отруєним подарунком ...
Андре Карон

1
@Andre - звичайно, якщо ви вирішите використовувати бібліотеку, яка вимагає змінних станів та імперативної семантики, вам доведеться керувати цим. Це нічим не відрізняється від того, якщо ви отримували доступ до такої бібліотеки з будь-якої іншої мови. Але у вас є два пристойні варіанти: а) не використовуйте такі бібліотеки - ви можете писати цілком хороший код чистою мовою Clojure або б) обгортайте складність взаємодії з цими бібліотеками в приємний функціональний інтерфейс у стилі Clojure, який зазвичай легко макроси або агенти тощо. Загалом, я знайшов можливість використання бібліотек Java набагато більшою перевагою, ніж це проблема.
mikera

4
@mikera: бібліотеки мають переваги. Я лише зазначаю, що використання бібліотек Java (це одна з основних цілей Річа Хікі для мови) насправді суперечить "більш функціональному, ніж інші шліфувальні" аспекти Clojure. Мій коментар мав на увазі: "якщо ви не перепишете / не обернете ці бібліотеки, ви отримаєте імперативний код і не отримаєте вигоди від приємніших частин Clojure".
Андре Карон,

10

Ось гарне відео з порівнянням Scheme (в основному ракетки) та Clojure .

Справедливості заради, у Racket є синтаксис цукру (додаткові матеріали для зчитування) для типів даних (#hash, #, квадратні дужки тощо)

Плюс, єдиним способом Clojure зробити правильний recurзворотний виклик є використання , це мінус компіляції в JVM.

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


Я думаю, що посилання мертве.
nawfal

1
@nawfal Я думаю, що я це виправив
Daniil

6
Посилання мертве (знову?)
Викиньте рахунок

1
Схоже, відео за цим посиланням можна знайти тут: vimeo.com/22675078 .
GDP2,

Є також trampolineдля хвостових дзвінків.
HappyFace
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.