Celem mojego pytania nie jest rozpoczęcie wojny o płomienie, ale raczej określenie, w jakich okolicznościach każdy język jest „najlepszym narzędziem do pracy”.
Przeczytałem kilka książek o Clojure ( Programming Clojure , Practical Clojure , The Joy of Clojure i Manning Early Access Edition of Clojure in Action ) i myślę, że to fantastyczny język. Obecnie czytam Let Over Lambda, który zajmuje się głównie makrami Common Lisp i jest również bardzo interesującym językiem.
Ja nie Lisp ekspert (więcej początkujących), ale to rodzina języków fascynuje mnie, podobnie jak programowanie funkcyjne, w ogóle.
Zalety Clojure (i wady „innych”):
Działa na JVM.
JVM to bardzo stabilne, wydajne środowisko językowe, które całkiem dobrze spełnia marzenie Sun'a o „Napisz raz, uruchom [prawie] wszędzie”. Mogę pisać kod na moim Macbooku Pro, skompilować go do wykonywalnego pliku JAR, a następnie uruchomić go w systemie Linux i Microsoft Windows z niewielkimi dodatkowymi testami.
JVM (Hotspot i inne) obsługuje wysokiej jakości wyrzucanie elementów bezużytecznych oraz bardzo wydajną kompilację i optymalizację w trybie just-in-time. Tam, gdzie jeszcze kilka lat temu pisałem wszystko, co musiało działać szybko w C, teraz nie waham się robić tego w Javie.
Model standardowy, prosty, wielowątkowy. Czy Common Lisp ma standardowy pakiet wielowątkowy?
Zrywa monotonię wszystkich tych nawiasów za pomocą
[]
,{}
i#{}
chociaż eksperci Common Lisp prawdopodobnie powiedzą mi, że za pomocą makr czytnika można je dodać do CL.
Wady Clojure :
- Działa na JVM.
- Bez rekurencji ogona lub kontynuacji. Czy Common Lisp obsługuje kontynuacje? Uważam, że program wymaga wsparcia dla obu.
Zalety innych (w szczególności Common Lisp) (i wady Clojure):
Definiowane przez użytkownika makra czytnika.
Inne zalety?
Myśli? Inne różnice?
źródło
Odpowiedzi:
Moja osobista lista powodów, dla których wolę Clojure od innych Lispsów (ps, nadal uważam, że wszystkie Lispy są świetne!):
Działa na JVM - w ten sposób uzyskuje automatyczny dostęp do fantastycznej inżynierii w samej JVM (zaawansowane algorytmy zbierania śmieci, optymalizacja HotSpot JIT itp.)
Bardzo dobra interoperacyjność Java - zapewnia kompatybilność z szeroką gamą bibliotek w ekosystemie języków Java / JVM. Użyłem Clojure jako języka „klejącego” do łączenia różnych bibliotek Java z dobrym skutkiem. Ponieważ opracowuję również dużo kodu Java, pomocne jest dla mnie to, że Clojure dobrze integruje się z narzędziami Java (np. Używam Maven, Eclipse z wtyczką Counterclockwise do mojego rozwoju Clojure)
Niezła składnia wektorów
[1 2 3]
, map{:bob 10, :jane 15}
i zestawów#{"a" "b" "c"}
- uważam te dość niezbędne narzędzia do współczesnego programowania (oprócz list oczywiście!)Osobiście podoba mi się używanie nawiasów kwadratowych do oprawiania formularzy: np.
(defn foo [a b] (+ a b))
- Myślę, że dzięki temu kod jest nieco bardziej czytelny.Nacisk na leniwe, funkcjonalne programowanie z trwałymi, niezmiennymi strukturami danych - w szczególności cała podstawowa biblioteka Clojure została zaprojektowana do obsługi tego domyślnie
Doskonała implementacja STM dla współbieżności wielordzeniowej. Uważam, że Clojure ma obecnie najlepszą historię współbieżności ze wszystkich języków (zobacz ten film, aby uzyskać więcej informacji od samego Richa Hickeya )
To Lisp-1 (jak Scheme), który osobiście wolę (myślę, że w języku funkcjonalnym sensowne jest utrzymywanie funkcji i danych w tej samej przestrzeni nazw)
źródło
Należy pamiętać, że Clojure to język i implementacja (zwykle w JVM). Common Lisp to język z ponad dziesięcioma różnymi implementacjami. Mamy więc tutaj niedopasowanie kategorii. Możesz na przykład porównać Clojure z SBCL.
Ogólnie:
wersja Common Lisp działa na JVM: ABCL
większość innych implementacji Common Lisp nie
większość implementacji CL ma możliwości wielozadaniowości, biblioteka zapewnia wspólny interfejs
Common Lisp ma składnię dla tablic. Składnia dla innych typów danych może być napisana przez użytkownika i są one dostarczane przez różne biblioteki.
Common Lisp nie obsługuje ani optymalizacji wywołań końcowych, ani kontynuacji. Wdrożenia zapewniają całkowity koszt posiadania, a biblioteki zapewniają pewną formę kontynuacji.
źródło
Ważną różnicą między Clojure a Common Lisp jest to, że Clojure jest bardziej nakazowy w zakresie programowania funkcjonalnego. Filozofia Clojure, idiomy i do pewnego stopnia język / biblioteki silnie zachęcają, a czasami nalegają, aby programować w funkcjonalny sposób (bez skutków ubocznych, bez zmiennego stanu).
Common Lisp zdecydowanie obsługuje programowanie funkcjonalne, ale umożliwia również programowanie w trybie mutowalnym i imperatywnym.
Oczywiście programowanie funkcjonalne ma wiele zalet, jeśli chodzi o współbieżność i nie tylko. Ale skoro wszystko inne jest równe, dobrze jest mieć wybór, które podejście chcesz zastosować w każdej sytuacji. Clojure nie zabrania całkowicie programowania imperatywnego, ale jest mniej dostosowany do tego stylu niż Common Lisp.
źródło
Oto dobry film z porównaniem Scheme (głównie Racket) i Clojure .
Aby być uczciwym, Racket ma cukier składniowy (dodatkowe elementy czytnika) również dla typów danych (#hash, #, nawiasy kwadratowe itp.)
Dodatkowo, jedynym sposobem Clojure na wykonanie prawidłowego wywołania końcowego jest użycie
recur
, to jest wada kompilacji do JVM.źródło
trampoline
wywołanie ogonowe.