Clojure vs otros Lisps [cerrado]

93

La intención de mi pregunta no es iniciar una guerra de fuego, sino más bien determinar en qué circunstancias cada idioma es "la mejor herramienta para el trabajo".

He leído varios libros sobre Clojure ( Programming Clojure , Practical Clojure , The Joy of Clojure y la edición Manning Early Access de Clojure in Action ), y creo que es un lenguaje fantástico. Actualmente estoy leyendo Let Over Lambda, que se ocupa principalmente de macros Common Lisp, y también es un lenguaje muy interesante.

Estoy no un experto en Lisp (más de un novato), pero esta familia de lenguas me fascina, al igual que la programación funcional, en general.

Ventajas de Clojure (y desventajas de "otros"):

  • Se ejecuta en la JVM.

    • La JVM es un entorno de lenguaje muy estable y de alto rendimiento que cumple bastante bien con el sueño de Sun de "Escribir una vez, ejecutar [casi] en cualquier lugar". Puedo escribir código en mi Macbook Pro, compilarlo en un archivo JAR ejecutable y luego ejecutarlo en Linux y Microsoft Windows con pocas pruebas adicionales.

    • La JVM (Hotspot y otras) admite la recolección de basura de alta calidad y una compilación y optimización just-in-time de gran rendimiento. Donde hace apenas unos años escribí todo lo que tenía que correr rápido en C, ahora no dudo en hacerlo en Java.

    • Modelo estándar, simple y de múltiples subprocesos. ¿Common Lisp tiene un paquete estándar de subprocesos múltiples?

    • Rompe la monotonía de todos esos paréntesis con [], {}y #{}, aunque los expertos en Common Lisp probablemente me dirán que con las macros de lector, puedes agregarlas a CL.

Desventajas de Clojure :

  • Se ejecuta en la JVM.
    • Sin recursividad o continuaciones de cola. ¿Common Lisp admite continuaciones? El esquema requiere apoyo para ambos, creo.

Ventajas de otros (Common Lisp, en particular) (y desventajas de Clojure):

  • Macros de lector definibles por el usuario.

  • Otras ventajas?

Pensamientos Otras diferencias?

Ralph
fuente
15
personalmente me gusta un tipo de paréntesis;) parece un código "más limpio"
Moe
3
Por lo que leí en su lista de ventajas, me imagino que tal vez también le guste Erlang www.erlang.org
Peer Stritzinger
4
Clojure admite la recursividad de cola explícita a través de la forma especial "recur". Esto le permite obtener todos los beneficios de la recursividad de cola siempre que lo solicite explícitamente (la única excepción es que actualmente no admite recursiones de cola mutuas entre múltiples funciones).
mikera
1
Clojure también admite continuaciones, al menos en el sentido de "estilo de paso de continuación". Tiene razón en que no tiene continuaciones de primera clase. ver stackoverflow.com/questions/1173133/continuations-in-clojure
mikera
@mikera: recursividad de cola en una función. Dos funciones que se llaman entre sí tienen que hacerse con "trampolín", que es algo torpe (pero elegante a su manera :-)).
Ralph

Respuestas:

52

Mi lista personal de razones para preferir Clojure a otros Lisps (ps, ¡todavía creo que todos los Lisps son geniales!):

  • Se ejecuta en la JVM, por lo que obtiene acceso automático a la fantástica ingeniería de la propia JVM (algoritmos avanzados de recolección de basura, optimización HotSpot JIT, etc.)

  • Muy buena interoperabilidad de Java: proporciona compatibilidad con la amplia gama de bibliotecas del ecosistema de lenguajes Java / JVM. He usado Clojure como un lenguaje de "pegamento" para conectar diferentes bibliotecas de Java con buen efecto. Como también desarrollo una gran cantidad de código Java, es útil para mí que Clojure se integre bien con las herramientas de Java (por ejemplo, uso Maven, Eclipse con el complemento Counterclockwise para mi desarrollo de Clojure)

  • Buena sintaxis para vectores [1 2 3], mapas {:bob 10, :jane 15}y conjuntos #{"a" "b" "c"}: considero estas herramientas bastante esenciales para la programación moderna (¡además de las listas, por supuesto!)

  • Personalmente, me gusta el uso de corchetes para encuadernar formularios: por ejemplo (defn foo [a b] (+ a b)), creo que hace que el código sea un poco más claro de leer.

  • Énfasis en la programación funcional y perezosa con estructuras de datos persistentes e inmutables; en particular, toda la biblioteca central de Clojure está diseñada para admitir esto de forma predeterminada

  • Excelente implementación de STM para la concurrencia de múltiples núcleos. Creo que Clojure tiene la mejor historia de concurrencia de cualquier idioma en este momento (vea este video para obtener más información del propio Rich Hickey )

  • Es un Lisp-1 (como Scheme), que personalmente prefiero (creo que en un lenguaje funcional tiene sentido mantener las funciones y los datos en el mismo espacio de nombres)

mikera
fuente
2
+1 para el STM. Es, por sí solo, suficiente para justificar el uso de Clojure.
André Caron
2
Aún puede obtener STM usando la biblioteca CL-STM.
Mike Manilone
2
@ AndréCaron solo si lo necesitas.
pliegue derecho
Si quisiera escribir una aplicación web simple y alojarla en, digamos, un host barato de $ 5 / mes, obviamente no es posible con Clojure debido a JVM, ¿correcto?
Hexatonic
@Hexatonic No tengo mucha experiencia, pero es difícil creer que una máquina en uso en estos días no tenga una JVM.
MasterMastic
25

Tenga en cuenta que Clojure es un lenguaje y una implementación (generalmente en la JVM). Common Lisp es un lenguaje con más de diez implementaciones diferentes. Entonces tenemos una discrepancia de categoría aquí. Por ejemplo, podría comparar Clojure con SBCL.

Generalmente:

  • una versión de Common Lisp se ejecuta en la JVM: ABCL

  • la mayoría de las demás implementaciones de Common Lisp no

  • la mayoría de las implementaciones de CL tienen capacidades multitarea, una biblioteca proporciona una interfaz común

  • Common Lisp tiene sintaxis para matrices. El usuario puede escribir la sintaxis de otros tipos de datos y la proporcionan varias bibliotecas.

  • Common Lisp no admite la optimización de llamadas de cola ni las continuaciones. Las implementaciones proporcionan TCO y las bibliotecas proporcionan alguna forma de continuación.

Rainer Joswig
fuente
24

Una diferencia importante entre Clojure y Common Lisp es que Clojure es más prescriptivo sobre la programación funcional. La filosofía, los modismos y, hasta cierto punto, los lenguajes / bibliotecas de Clojure alientan fuertemente y, a veces, insisten en que programe de manera funcional (sin efectos secundarios, sin estado mutable).

Common Lisp definitivamente admite la programación funcional, pero también permite el estado mutable y la programación imperativa.

Por supuesto, hay una serie de beneficios para la programación funcional, en el área de concurrencia y otros. Pero en igualdad de condiciones, también es bueno poder elegir el enfoque que desea utilizar para cada situación. Clojure no prohíbe completamente la programación imperativa, pero se adapta menos a ese estilo que Common Lisp.

Charlie Flores
fuente
3
@Charlie Flowers: Creo que en Common Lisp es posible programar en un estilo "puramente funcional" (soporte de estructura de datos persistente, etc.), pero requiere disciplina. ¿Correcto?
Ralph
2
Solo una aclaración sobre "sin efectos secundarios, sin estado mutable": Clojure tiene un estado mutable (las referencias, los átomos, los agentes, etc.son todos mutables) pero requiere que acceda a él de manera controlada (es decir, a través de los mecanismos STM y transacciones relacionadas semántica de actualización)
mikera
5
@mikera: excepto que Clojure se basa en el uso de bibliotecas Java para ser utilizable, y todas esas bibliotecas requieren un estilo imperativo y están llenas de efectos secundarios. Descubrí que los enlaces con Java son un regalo envenenado ...
André Caron
1
@Andre: claro, si decide usar una biblioteca que requiere un estado mutable y una semántica imperativa, entonces debe administrar esto. Esto no es diferente de si accediera a dicha biblioteca desde cualquier otro idioma. Pero tiene dos opciones decentes: a) No use tales bibliotecas: puede escribir un código perfectamente bueno en Clojure puro ob) envolver la complejidad de interactuar con estas bibliotecas en una agradable interfaz funcional estilo Clojure, que generalmente es fácil con macros o agentes, etc. En general, he encontrado que la capacidad de aprovechar las bibliotecas de Java es un beneficio mucho mayor que un problema.
mikera
4
@mikera: las bibliotecas tienen un beneficio. Solo estoy señalando que el uso de bibliotecas Java (este es uno de los objetivos principales de Rich Hickey para el lenguaje) realmente va en contra del aspecto "más funcional que otros lisps" de Clojure. Mi comentario tenía la intención de significar: "a menos que reescriba / envuelva estas bibliotecas, obtendrá un código de aspecto imperativo y no se beneficiará de las partes más agradables de Clojure".
André Caron
10

Aquí hay un buen video con una comparación de Scheme (Racket principalmente) y Clojure .

Para ser justos, Racket también tiene azúcar de sintaxis (material de lectura adicional) para los tipos de datos (#hash, #, corchetes, etc.)

Además, la única forma de Clojure de hacer una llamada de cola adecuada es usar recur, esa es la desventaja de compilar en JVM.

Tenga en cuenta que recures la única construcción de bucle que no consume pila en Clojure. No hay optimización de llamadas de cola y se desaconseja el uso de auto llamadas para realizar bucles de límites desconocidos. recures funcional y su uso en la posición final es verificado por el compilador. ( Formularios especiales ).

Daniil
fuente
Link está muerto, supongo.
nawfal
1
@nawfal Creo que lo arreglé
Daniil
6
Link is dead (¿otra vez?)
Throw Away Account
1
Parece que el video de ese enlace se puede encontrar aquí: vimeo.com/22675078 .
GDP2
También hay trampolinellamadas de cola.
HappyFace