lein instalar bridal clojure leiningen

bridal - instalar clojure



¿Cuál es la diferencia entre Cake y Leiningen? (4)

Como 2011-11-15, el anuncio de fusión pastel y lein

¿Cuál es la diferencia entre Cake y Leiningen?


Como Alex mencionó, la diferencia más llamativa es la velocidad desde la línea de comando. Cake utiliza una JVM persistente, por lo que solo encontrará la carga de inicio de jvm cuando ejecute una tarea dentro de su proyecto por primera vez. Si no está usando emacs + slime + clojure-test-mode, esto puede ser un gran ahorro de tiempo. Por ejemplo, un conjunto de pruebas razonablemente grande en uno de mis proyectos se ejecuta en 0.3 segundos en torta, frente a 11.2 en lein.

Además del rendimiento, la idea central detrás del pastel es el modelo de tarea de dependencia. Cada tarea solo se ejecuta una vez en una construcción determinada, teniendo en cuenta todos los requisitos previos transitivos en el gráfico de dependencia. Aquí hay un ejemplo del artículo de Martin Fowler sobre la sintaxis del rastrillo en la torta, que va directamente en su project.clj.

(deftask code-gen "This task generates code. It has no dependencies." (println "generating code...") ...) (deftask compile #{code-gen} "This task does the compilation. It depends on code-gen." (println "compiling...") ...) (deftask data-load #{code-gen} "This task loads the test data. It depends on code-gen." (println "loading test data...") ...) (deftask test #{compile data-load} "This task runs the tests. It depends on compile and data-load." (println "running tests...") ...)

Para hacer lo mismo en Leiningen, primero tendría que crear un directorio de leiningen en su proyecto con 4 archivos: code_gen.clj, compile.clj, data_load.clj y my_test.clj.

src / leiningen / code_gen.clj

(ns leiningen.code-gen "This task generates code. It has no dependencies.") (defn code-gen [] (println "generating code..."))

src / leiningen / my_compile.clj

(ns leiningen.my-compile "This task does the compilation. It depends on code-gen." (:use [leiningen.code-gen])) (defn my-compile [] (code-gen) (println "compiling..."))

src / leiningen / data_load.clj

(ns leiningen.data-load "This task loads the test data. It depends on code-gen." (:use [leiningen.code-gen])) (defn data-load [] (code-gen) (println "loading test data..."))

src / leiningen / my_test.clj

(ns leiningen.my-test "This task runs the tests. It depends on compile and data-load." (:use [leiningen.my-compile] [leiningen.data-load])) (defn my-test [] (my-compile) (data-load) (println "running tests..."))

Uno esperaría ...

generating code... compiling... loading test data... running tests...

Pero tanto la carga de datos como my-compile dependen de code-gen, por lo que su salida real es ...

generating code... compiling... generating code... loading test data... running tests...

Tendría que memorizar code-gen para evitar que se ejecute varias veces:

(ns leiningen.code-gen "This task generates code. It has no dependencies.") (def code-gen (memoize (fn [] (println "generating code..."))))

salida:

generating code... compiling... loading test data... running tests...

Que es lo que queremos

Las compilaciones son más simples y más eficientes si una tarea solo se ejecuta una vez por compilación, por lo que la convertimos en el comportamiento predeterminado en compilaciones. La filosofía tiene décadas de antigüedad y está compartida por un linaje de herramientas de construcción. Todavía puede usar funciones, puede llamarlas repetidamente y siempre tiene la potencia completa de clojure a su disposición.

Lein simplemente le proporciona una función simple como tarea, pero con la restricción adicional de que debe tener su propio espacio de nombres en src. Si una tarea depende de él, estará en un espacio de nombre separado, y debe usar / requerir el otro en su macro ns . Las compilaciones de pasteles se ven mucho más nítidas y concisas en comparación.

Otra diferencia clave es cómo se anexan las tareas. Digamos que queríamos agregar my-test como requisito previo para la tarea jar incorporada de cake / lein. En cake, puede usar la macro de deftask para agregar a las formas y dependencias de una tarea.

(deftask jar #{my-test})

Lein usa a Robert Hooke para anexar tareas. Es una biblioteca realmente genial, llamada así por el deftask natural favorito de todos, pero requeriría una macro por la concisión de deftask .

(add-hook #''leiningen.jar/jar (fn [f & args] (my-test) (apply f args)))

Cake también tiene la noción de un proyecto global. Puede agregar dependencias de desarrollo específicas del usuario, como swank, a ~/.cake/project.clj y ~/.cake/project.clj en todos sus proyectos. El proyecto global también se usa para iniciar una réplica fuera de un proyecto de experimentación. Lein implementa características similares al admitir la configuración por usuario en ~/.lein/init.clj , y los complementos globales en ~/.lein/plugins . En general, Lein actualmente tiene un ecosistema de plugin mucho más rico que cake, pero cake incluye más tareas listas para usar (guerra, implementación, compilación java, dependencias nativas, clojars y swank). Puede que valga la pena echarle un vistazo a Cljr, se trata básicamente de un proyecto global con un administrador de paquetes, pero sin capacidades de compilación (sin embargo, no tengo experiencia en ello).

La verdadera diferencia irreconcible son las definiciones de tareas, como lo señala la tecnomancia. En mi opinión (sesgada), Cake maneja las tareas mucho mejor. La necesidad de un modelo de dependencia de tareas se hizo evidente cuando comenzamos a utilizar los búferes de protocolo en nuestro proyecto con lein. Los protobufs son prerrequisitos para todas nuestras tareas, pero compilarlos es muy lento. También tenemos muchas tareas interdependientes, por lo que cualquier construcción fue dolorosa. Tampoco me gusta el requisito de un espacio de nombres separado, y por lo tanto un archivo src adicional, para cada tarea que creo. Los desarrolladores deben crear muchas tareas, el enfoque de Lein desalienta esto creando demasiada fricción. Con cake, puedes usar la macro de deftask dentro de project.clj.

Cake todavía es joven y un trabajo en progreso, pero es un proyecto muy activo.


Esta respuesta continúa generando interés, presumiblemente como una referencia para Leiningen en , por lo que ahora está editada significativamente para actualizarla en 2014.

Leiningen y Cake se fusionaron en 2011. Leiningen (versión 2) es ahora la herramienta de automatización Clojure de facto.

Leiningen es una herramienta de compilación y administrador de dependencias para Clojure que incluye la capacidad de configurar un REPL interactivo con el classpath configurado apropiadamente y con todas las dependencias java y clojure adquiridas de forma automática desde los repositorios maven y / o los Leiningen basados ​​en la comunidad.

Cake fue muy similar a Leiningen (hasta usar el mismo formato de archivo project.clj en ese momento), pero intentó evitar una gran sobrecarga de inicio al mantener las JVM persistentes en segundo plano. Esto fue más receptivo, pero se intercambió la conveniencia de errores debido al estado acumulado en los procesos persistentes (antiguas definiciones de funciones pendientes, etc.) sobre el curso típico de desarrollo basado en REPL iterativo. Esto resultó ser un mal negocio.

La experiencia con Leiningen y el continuo deseo de tiempos de puesta en marcha más rápidos han dado lugar a una serie de recomendaciones y enfoques para agilizar las cosas: https://github.com/technomancy/leiningen/wiki/Faster


La principal diferencia radica en la forma en que se implementan las tareas.

El enfoque de Cake es "es difícil ampliar funciones después de haberlas definido, así que vamos a inventar un nuevo mecanismo para tareas en lugar de usar funciones", lo que dio como resultado la macro deftask.

El enfoque de Leiningen es "es difícil ampliar funciones después de haberlas definido, así que debemos hacer una forma de hacerlo fácilmente, de esa manera podemos usar funciones para tareas y también poder extender cosas que no son tareas", que le permite aplicar todas las ventajas de compsabilidad de las funciones con las tareas.