Clojure Es PDF
Clojure Es PDF
Clojure Es PDF
#clojure
Tabla de contenido
Acerca de 1
Observaciones 2
Versiones 3
Examples 3
Instalación y configuración 3
Opción 1: Leiningen 3
Linux 3
OS X 3
Windows 4
Opción 3: Arranque 4
Examples 7
Capítulo 3: Átomo 8
Introducción 8
Examples 8
Define un átomo 8
Capítulo 4: clojure.core 10
Introducción 10
Examples 10
Definiendo funciones en clojure 10
Capítulo 5: clojure.spec 12
Sintaxis 12
Observaciones 12
Examples 12
Especificaciones de registro 14
Colecciones 15
Secuencias 17
Observaciones 18
Examples 18
Literales a juego 18
Emparejando un vector 18
Sintaxis 20
Examples 20
Colecciones 20
Liza 20
Secuencias 23
Vectores 27
Conjuntos 31
Mapas 33
Capítulo 8: Comenzando con el desarrollo web 39
Examples 39
Servidores web 40
bases de datos 40
diverso 40
Examples 42
Mesa ligera 42
Emacs 43
Átomo 43
Spacemacs + SIDRA 44
Empuje 45
Examples 46
Canales de cierre 47
Examples 50
Destructurando un vector 50
Destructurando un mapa 50
Visión general 52
Consejos: 53
Introducción 55
Examples 55
Evaluación de la función 55
Impresión bonita 55
Introducción 57
Examples 57
Examples 59
Definiendo funciones 59
Parámetros y Arity 59
Aridad 60
Sintaxis soportada 61
Sintaxis 63
Observaciones 63
Examples 63
Examples 65
La verdad 65
Booleanos 65
Sintaxis 66
Observaciones 66
Examples 66
Examples 69
Visión general 69
Notas: 69
Examples 70
es 70
son 71
Introducción 73
Observaciones 73
Examples 73
Ejemplos de matematicas 73
Introducción 74
Examples 74
Obtención Día Mes Año Hora Minuto Segundo desde su fecha y hora 74
Introducción 77
Observaciones 77
Examples 77
Aplicando transductores 78
Sintaxis 80
Observaciones 80
Examples 80
Tipos de variables 80
Creditos 81
Acerca de
You can share this PDF with anyone you feel could benefit from it, downloaded the latest version
from: clojure
It is an unofficial and free clojure ebook created for educational purposes. All the content is
extracted from Stack Overflow Documentation, which is written by many hardworking individuals at
Stack Overflow. It is neither affiliated with Stack Overflow nor official clojure.
The content is released under Creative Commons BY-SA, and the list of contributors to each
chapter are provided in the credits section at the end of this book. Images may be copyright of
their respective owners unless otherwise specified. All trademarks and registered trademarks are
the property of their respective company owners.
Use the content presented in this book at your own risk; it is not guaranteed to be correct nor
accurate, please send your feedback and corrections to [email protected]
https://riptutorial.com/es/home 1
Capítulo 1: Empezando con clojure
Observaciones
Sus características admiten el estilo funcional de programación con funciones de primera clase y
valores inmutables de forma predeterminada. El uso de variables reasignables no es tan fácil en
Clojure como en muchos idiomas convencionales, ya que las variables deben crearse y
actualizarse como objetos contenedores. Esto fomenta el uso de valores puros que
permanecerán como estaban en el momento en que fueron vistos por última vez. Por lo general,
esto hace que el código sea mucho más predecible, verificable y con capacidad de concurrencia.
Esto también funciona para las colecciones, ya que las estructuras de datos integradas de Clojure
son persistentes.
Para el rendimiento, Clojure admite sugerencias de tipo para eliminar la reflexión innecesaria
cuando sea posible. Además, se pueden realizar grupos de cambios en las colecciones
persistentes en versiones transitorias , lo que reduce la cantidad de objetos involucrados. Esto no
es necesario la mayoría del tiempo, ya que las colecciones persistentes se copian rápidamente ya
que comparten la mayoría de sus datos. Sus garantías de desempeño no están lejos de sus
contrapartes mutables.
Diseñado como un lenguaje alojado, puede interoperar con la plataforma en la que se ejecuta. Si
bien el objetivo principal es JVM y todo el ecosistema detrás de Java, también se pueden ejecutar
implementaciones alternativas en otros entornos, como ClojureCLR ejecutándose en Common
Language Runtime o ClojureScript ejecutándose en tiempos de ejecución de JavaScript (incluidos
https://riptutorial.com/es/home 2
los navegadores web). Si bien las implementaciones alternativas pueden carecer de algunas de
las funcionalidades de la versión JVM, todavía se consideran una familia de idiomas.
Versiones
1.2.1 2011-03-25
1.2 2010-08-19
1.1 2010-01-04
1.0 2009-05-04
Examples
Instalación y configuración
Opción 1: Leiningen
Requiere JDK 6 o más nuevo.
La forma más fácil de comenzar con Clojure es descargar e instalar Leiningen, la herramienta
estándar de facto para administrar proyectos de Clojure, y luego ejecutar el lein repl para abrir
un REPL .
Linux
OS X
https://riptutorial.com/es/home 3
Siga los pasos de Linux anteriores o instale con los administradores de paquetes macOS.
lein self-install
Windows
Las versiones de Clojure se publican como archivos JAR simples que se ejecutan en la JVM. Esto
es lo que sucede típicamente dentro de las herramientas de construcción de Clojure.
Puede que tenga que sustituir el clojure-1.8.0.jar en ese comando por el nombre del
archivo JAR que realmente descargó.
Para una mejor experiencia de REPL en la línea de comandos (por ejemplo, rlwrap los
comandos anteriores), es posible que desee instalar rlwrap : rlwrap java -cp clojure-
1.8.0.jar clojure.main
Opción 3: Arranque
Requiere JDK 7 o más nuevo.
Boot es una herramienta de compilación Clojure de usos múltiples. Comprenderlo requiere cierto
https://riptutorial.com/es/home 4
conocimiento de Clojure, por lo que puede que no sea la mejor opción para los principiantes.
Consulte el sitio web (haga clic en Comenzar allí) para obtener instrucciones de instalación.
Una vez que esté instalado y en su PATH , puede ejecutar boot repl cualquier lugar para iniciar un
Clojure REPL.
La comunidad de Clojure pone un gran énfasis en el desarrollo interactivo, por lo que una gran
cantidad de interacción con Clojure ocurre dentro de un REPL (read-eval-print-loop) . Cuando
ingresas una expresión en ella, Clojure la lee , la evalúa e imprime el resultado de la evaluación,
todo en un bucle .
Ya deberías poder lanzar un Clojure REPL. Si no sabe cómo hacerlo, siga las instrucciones de
instalación y configuración de este tema. Una vez que lo tienes funcionando, escribe lo
siguiente en él:
Luego presiona Enter . Esto debería imprimir Hello, world! , seguido del valor de retorno de esta
expresión, nil .
Si desea ejecutar un poco de clojure al instante, intente REPL en línea. Por ejemplo
http://www.tryclj.com/ .
Después de seguir las instrucciones anteriores e instalar Leiningen, inicie un nuevo proyecto
ejecutando:
Suponiendo que utilizó la plantilla de la aplicación para crear una nueva aplicación, puede probar
que todo se configuró correctamente, ingresando al directorio creado y ejecutando la aplicación
usando:
lein run
Si ves Hello, World! en su consola, está todo listo y listo para comenzar a construir su aplicación.
https://riptutorial.com/es/home 5
Puede empaquetar esta sencilla aplicación en dos archivos jar con el siguiente comando:
lein uberjar
Nota: necesitas instalar Boot antes de probar este ejemplo. Consulte la sección Instalación y
configuración si aún no lo ha instalado.
Boot permite crear archivos ejecutables de Clojure utilizando la línea shebang (#!). Coloque el
siguiente texto en un archivo de su elección (este ejemplo asume que está en el "directorio de
trabajo actual" y se llama hello.clj ).
#!/usr/bin/env boot
Luego chmod +x hello.clj como ejecutable (si corresponde, normalmente ejecutando chmod +x
hello.clj ).
... y ejecutarlo ( ./hello.clj ).
Para ejecutar la aplicación: boot run . Otros comandos se especifican en build.boot y se describen
en README.
https://riptutorial.com/es/home 6
Capítulo 2: Analizando troncos con clojure
Examples
Analizar una línea de registro con registro y expresiones regulares
Pruébalo :
(parser sample)
Resultado:
https://riptutorial.com/es/home 7
Capítulo 3: Átomo
Introducción
Un átomo en Clojure es una variable que se puede cambiar a lo largo de su programa (espacio de
nombres). Debido a que la mayoría de los tipos de datos en Clojure son inmutables (o
inmutables), no se puede cambiar el valor de un número sin redefinirlo, los átomos son esenciales
en la programación de Clojure.
Examples
Define un átomo
Para definir un átomo, use una def ordinaria, pero agregue una función de atom delante de él, así:
Esto crea un atom de valor 0 . Los átomos pueden ser de cualquier tipo:
Para leer el valor de un átomo, simplemente ponga el nombre del átomo, con una @ antes de él:
@counter ; => 0
Hay dos comandos para cambiar un átomo, swap! y reset! . swap! recibe comandos y cambia el
átomo en función de su estado actual. reset! cambia el valor del átomo por completo,
independientemente de cuál sea el valor del átomo original:
https://riptutorial.com/es/home 8
(def count (atom 0))
https://riptutorial.com/es/home 9
Capítulo 4: clojure.core
Introducción
Este documento da varias funcionalidades básicas ofrecidas por clojure. No se necesita una
dependencia explícita para esto y se incluye como parte de org.clojure.
Examples
Definiendo funciones en clojure
(defn x [a b]
(* a b)) ;; public function
=> (x 3 2) ;; 6
=> (x 0 9) ;; 0
(defn- y [a b]
(+ a b)) ;; private function
=> (x (y 1 2) (y 2 3)) ;; 15
Cuando se aplica en un mapa, devuelve un nuevo mapa con pares de valores clave nuevos o
actualizados.
(assoc [3 5 6 7] 2 10) ;; [3 5 10 7]
(assoc [1 2 3 4] 6 6) ;; java.lang.IndexOutOfBoundsException
Las comparaciones son funciones en clojure. Lo que eso significa en (2>1) es (> 2 1) en clojure.
Aquí están todos los operadores de comparación en clojure.
https://riptutorial.com/es/home 10
1. Mas grande que
(> 2 1) ;; true
(> 1 2) ;; false
2. Menos que
(< 2 1) ;; false
(>= 2 1) ;; true
(>= 2 2) ;; true
(>= 1 2) ;; false
(<= 2 1) ;; false
(<= 2 2) ;; true
(<= 1 2) ;; true
5. Igual a
(= 2 2) ;; true
(= 2 10) ;; false
6. No igual a
(not= 2 2) ;; false
(not= 2 10) ;; true
Esto devuelve un mapa sin los pares clave-valor para las claves mencionadas en el argumento de
la función. Se puede utilizar para eliminar información del mapa existente.
https://riptutorial.com/es/home 11
Capítulo 5: clojure.spec
Sintaxis
• :: es una abreviatura de palabra clave calificada para el espacio de nombres. Por ejemplo, si
estamos en el espacio de nombres de usuario: :: foo es una abreviatura de: user / foo
• #: o # - sintaxis literal del mapa para calificar claves en un mapa por un espacio de nombres
Observaciones
Clojure spec es una nueva biblioteca de especificación / contratos para clojure disponible a partir
de la versión 1.9.
Examples
Usando un predicado como una especificación
Cualquier función de predicado se puede utilizar como una especificación. Aquí hay un ejemplo
simple:
(clojure.spec/valid? odd? 1)
;;=> true
(clojure.spec/valid? odd? 2)
;;=> false
Podemos escribir una especificación para esta función definiendo una especificación de función
con el mismo nombre:
https://riptutorial.com/es/home 12
(clojure.spec/fdef nat-num-count
:args (s/cat :nums (s/coll-of number?))
:ret integer?
:fn #(<= (:ret %) (-> % :args :nums count)))
:args toma una especificación de expresiones regulares que describe la secuencia de argumentos
por una etiqueta de palabra clave correspondiente al nombre del argumento y una especificación
correspondiente. La razón por la que la especificación requerida por :args es una especificación
de expresiones regulares es para admitir múltiples aridades para una función. :ret especifica una
especificación para el valor de retorno de la función.
:fnes una especificación que restringe la relación entre :args y :ret . Se utiliza como una
propiedad cuando se ejecuta a través de test.check. Se llama con un solo argumento: un mapa
con dos claves:: :args (los argumentos conformes a la función) y :ret (el valor de retorno
conformado de la función).
Además de los predicados que funcionan como especificaciones, puede registrar una
especificación global usando clojure.spec/def . def requiere que una especificación que se está
registrando sea nombrada por una palabra clave calificada para el espacio de nombres:
(clojure.spec/valid? ::odd-nums 1)
;;=> true
(clojure.spec/valid? ::odd-nums 2)
;;=> false
Una vez registrada, una especificación puede ser referenciada globalmente en cualquier lugar en
un programa de Clojure.
clojure.spec/and & clojure.spec/or puede usarse para crear especificaciones más complejas,
utilizando múltiples especificaciones o predicados:
(clojure.spec/valid? ::pos-odd 1)
;;=> true
https://riptutorial.com/es/home 13
or funciona de manera similar, con una diferencia significativa. Al definir una or espec., Debe
etiquetar cada rama posible con una palabra clave. Esto se usa para proporcionar ramas
específicas que fallan en los mensajes de error:
(clojure.spec/valid? ::big-or-small 1)
;;=> true
(clojure.spec/conform ::big-or-small 5)
;; => [:small 5]
Especificaciones de registro
En algún momento en el futuro, se puede introducir una sintaxis de lector o un soporte integrado
para calificar las claves de registro por el espacio de nombres de los registros. Este soporte ya
existe para los mapas.
Puede especificar un mapa especificando qué claves deben estar presentes en el mapa:
https://riptutorial.com/es/home 14
(clojure.spec/valid? ::person {::name "john" ::age 25 ::occupation "programmer"})
;; => true
:req es un vector de claves que deben estar presentes en el mapa. Puede especificar opciones
adicionales como :opt , un vector de claves que son opcionales.
Los ejemplos hasta ahora requieren que las claves en el nombre estén calificadas para el espacio
de nombres. Pero es común que las claves del mapa no estén calificadas. Para este caso,
clojure.spec proporciona: req y: opt equivalentes para claves no calificadas :req-un y :opt-un .
Aquí está el mismo ejemplo, con claves no calificadas:
La sintaxis literal del mapa de espacio de nombres le permite calificar de manera sucinta todas las
claves de un mapa por un solo espacio de nombres. Por ejemplo:
Fíjate en la #: especial #: sintaxis del lector. Seguimos esto con el espacio de nombres por el que
deseamos calificar todas las claves de mapa. Estos se compararán con las especificaciones
correspondientes al espacio de nombres proporcionado.
Colecciones
https://riptutorial.com/es/home 15
Las opciones de restricción siguen la especificación / predicado principal de la colección. Puede
restringir el tipo de colección con :kind como este:
coll-of asegura que todos los elementos en una secuencia son verificados. Para grandes
colecciones, esto puede ser muy ineficiente. every comporta como una coll-of , excepto que solo
muestrea un número relativamente pequeño de elementos de las secuencias para su
conformidad. Esto funciona bien para grandes colecciones. Aquí hay un ejemplo:
map-of es similar a coll-of , pero para mapas. Como los mapas tienen tanto claves como valores,
https://riptutorial.com/es/home 16
debe proporcionar una especificación para la clave y una especificación para el valor:
Al igual que la coll-of , la map-of controles cumple con todas las claves / valores del mapa. Para
mapas grandes esto será ineficiente. Al igual que la coll-of , map-of suministra every-kv para
muestrear de manera eficiente un número relativamente pequeño de valores de un mapa grande:
Secuencias
La especificación puede describirse y usarse con secuencias arbitrarias. Es compatible con esto a
través de una serie de operaciones de especificación de expresiones regulares.
catrequiere etiquetas para cada especificación utilizada para describir la secuencia. El gato
describe una secuencia de elementos y una especificación para cada uno.
altse utiliza para elegir entre una serie de posibles especificaciones para un elemento dado en
una secuencia. Por ejemplo:
alt también requiere que cada especificación esté etiquetada por una palabra clave.
Las secuencias Regex se pueden componer de formas muy interesantes y potentes para crear
especificaciones de descripciones de secuencias arbitrariamente complejas. Aquí hay un ejemplo
un poco más complejo:
Aquí ::complex-seq validará una secuencia de uno o más pares de elementos, el primero es un int
y el segundo es un mapa de palabra clave para int.
https://riptutorial.com/es/home 17
Capítulo 6: Coincidencia de patrones con
core.match
Observaciones
La biblioteca core.match implementa un algoritmo de compilación de coincidencia de patrones que
utiliza la noción de "necesidad" de la coincidencia de patrones diferida.
Examples
Literales a juego
(let [x true
y true
z true]
(match [x y z]
[_ false true] 1
[false true _ ] 2
[_ _ false] 3
[_ _ true] 4))
;=> 4
Emparejando un vector
(let [v [1 2 3]]
(match [v]
[[1 1 1]] :a0
[[1 _ 1]] :a1
[[1 2 _]] :a2)) ;; _ is used for wildcard matching
;=> :a2
;=> :a1
(match [['asymbol]]
[['asymbol]] :success)
https://riptutorial.com/es/home 18
;=> :success
https://riptutorial.com/es/home 19
Capítulo 7: Colecciones y secuencias
Sintaxis
• '() → ()
• '(1 2 3 4 5) → (1 2 3 4 5)
• '(1 foo 2 bar 3) → (1 'foo 2 'bar 3)
• ( list 1 2 3 4 5) → (1 2 3 4 5)
• ( list* [1 2 3 4 5]) → (1 2 3 4 5)
• [] → []
• [1 2 3 4 5] → [1 2 3 4 5]
• ( vector 1 2 3 4 5) → [1 2 3 4 5]
• ( vec '(1 2 3 4 5)) → [1 2 3 4 5]
• {} => {}
• {:keyA 1 :keyB 2} → {:keyA 1 :keyB 2}
• {:keyA 1, :keyB 2} → {:keyA 1 :keyB 2}
• ( hash-map :keyA 1 :keyB 2) → {:keyA 1 :keyB 2}
• ( sorted-map 5 "five" 1 "one") → {1 "one" 5 "five"} (las entradas se ordenan por clave
cuando se usan como una secuencia)
• #{} → #{}
• #{1 2 3 4 5} → #{4 3 2 5 1} (sin ordenar)
• ( hash-set 1 2 3 4 5) → #{2 5 4 1 3} (sin ordenar)
• ( sorted-set 2 5 4 3 1) → #{1 2 3 4 5}
Examples
Colecciones
Todas las colecciones de Clojure integradas son inmutables y heterogéneas, tienen una sintaxis
literal y admiten las funciones conj , count y seq .
• devuelve una nueva colección que es equivalente a una colección existente con un
conj
elemento "agregado", ya sea en "constante" o tiempo logarítmico. Lo que exactamente esto
significa depende de la colección.
• count devuelve el número de elementos en una colección, en tiempo constante.
• seq devuelve nil para una colección vacía, o una secuencia de elementos para una
colección no vacía, en tiempo constante.
Liza
()
https://riptutorial.com/es/home 20
;;=> ()
Una lista de Clojure es una lista enlazada individualmente . conj "combina" un nuevo elemento de
la colección en la ubicación más eficiente. Para listas, esto es al principio:
(conj () :foo)
;;=> (:foo)
A diferencia de otras colecciones, las listas no vacías se evalúan como llamadas a formularios
especiales, macros o funciones cuando se evalúan. Por lo tanto, mientras que (:foo) es la
representación literal de la lista que contiene :foo como su único elemento, evaluar (:foo) en un
REPL provocará que se IllegalArgumentException una IllegalArgumentException porque una
palabra clave no puede invocarse como una función nula .
(:foo)
;; java.lang.IllegalArgumentException: Wrong number of args passed to keyword: :foo
Para evitar que Clojure evalúe una lista no vacía, puede quote :
'(:foo)
;;=> (:foo)
'(:foo :bar)
;;=> (:foo :bar)
(+ 1 1)
;;=> 2
'(1 (+ 1 1) 3)
;;=> (1 (+ 1 1) 3)
Por esta razón, normalmente querrá usar list , una función variadic que evalúa todos sus
argumentos y utiliza esos resultados para construir una lista:
(list)
;;=> ()
(list :foo)
;;=> (:foo)
(list 1 (+ 1 1) 3)
;;=> (1 2 3)
https://riptutorial.com/es/home 21
(count ())
;;=> 0
(list? ())
;;=> true
(list? nil)
;;=> false
(list? 42)
;;=> false
(list? :foo)
;;=> false
(peek ())
;;=> nil
(peek '(:foo))
;;=> :foo
Puedes obtener una nueva lista sin el primer elemento usando pop :
(pop '(:foo))
;;=> ()
Tenga en cuenta que si intenta pop una lista vacía, obtendrá un IllegalStateException :
(pop ())
;; java.lang.IllegalStateException: Can't pop empty list
Finalmente, todas las listas son secuencias, por lo que puede hacer todo con una lista que puede
hacer con cualquier otra secuencia. De hecho, con la excepción de la lista vacía, llamar a seq en
una lista devuelve el mismo objeto exacto:
https://riptutorial.com/es/home 22
(seq ())
;;=> nil
(seq '(:foo))
;;=> (:foo)
Secuencias
Una secuencia es muy parecida a una lista: es un objeto inmutable que puede darle su first
elemento o el rest de sus elementos en tiempo constante. También puede cons truct una nueva
secuencia de una secuencia existente y un elemento para pegarse al principio.
(seq? nil)
;;=> false
(seq? 42)
;;=> false
(seq? :foo)
;;=> false
(seq? ())
;;=> true
Todo lo que obtenga al llamar a seq o rseq o las keys o vals en una colección no vacía también es
una secuencia:
https://riptutorial.com/es/home 23
(seq? (rseq [:foo :bar]))
;;=> true
Recuerde que todas las listas son secuencias, pero no todas las secuencias son listas. Mientras
que las listas admiten peek y pop y count en tiempo constante, en general, una secuencia no
necesita admitir ninguna de esas funciones. Si intentas llamar peek o pop en una secuencia que no
es compatible con la interfaz de pila de Clojure, obtendrás una ClassCastException :
https://riptutorial.com/es/home 24
obtendrá un error; en su lugar, Clojure recorrerá toda la secuencia hasta que llegue al final, luego
devolverá el número de elementos que atravesó. Esto significa que, para secuencias generales,
el count es lineal, no constante, en el tiempo. ¿Puede probar si algo admite el count tiempo
constante usando el counted? predicado:
Como se mencionó anteriormente, puede usar first para obtener el primer elemento de una
secuencia. Tenga en cuenta que first llamará a seq en su argumento, por lo que se puede usar
en cualquier cosa "seqable", no solo en secuencias reales:
(first nil)
;;=> nil
(first '(:foo))
;;=> :foo
(first [:foo])
;;=> :foo
(first #{:foo})
;;=> :foo
También como se mencionó anteriormente, puede usar el rest para obtener una secuencia que
contenga todo menos el primer elemento de una secuencia existente. Como first , llama a la seq
https://riptutorial.com/es/home 25
en su argumento. Sin embargo, no llama a la seq en su resultado! Esto significa que, si llama a
rest en una secuencia que contiene menos de dos elementos, obtendrá back () lugar de nil :
(rest nil)
;;=> ()
(rest '(:foo))
;;=> ()
(rest [:foo])
;;=> ()
(rest #{:foo})
;;=> ()
Si desea volver a nil cuando no hay más elementos en una secuencia, puede usar next lugar de
rest :
(next nil)
;;=> nil
(next '(:foo))
;;=> nil
(next [:foo])
;;=> nil
Puede usar la función cons para crear una nueva secuencia que devolverá su primer argumento
para el first argumento y su segundo argumento para el rest :
Clojure proporciona una gran biblioteca de secuencias con muchas funciones para tratar con
secuencias. Lo importante de esta biblioteca es que funciona con cualquier cosa "seqable", no
solo con listas. Es por eso que el concepto de una secuencia es tan útil; significa que una sola
función, como reduce , funciona perfectamente en cualquier colección:
(reduce + [1 2 3])
;;=> 6
https://riptutorial.com/es/home 26
(reduce + #{1 2 3})
;;=> 6
La otra razón por la que las secuencias son útiles es que, dado que no requieren ninguna
implementación particular de first y rest , permiten secuencias perezosas cuyos elementos solo
se realizan cuando es necesario.
Dada una expresión que crearía una secuencia, puede envolver esa expresión en la macro lazy-
seq para obtener un objeto que actúe como una secuencia, pero solo evaluará esa expresión
cuando la función seq le pida que lo haga, en en qué punto almacenará en caché el resultado de
la expresión y reenviará las first y rest llamadas al resultado en caché.
Para secuencias finitas, una secuencia perezosa generalmente actúa de la misma manera que
una secuencia ansiosa equivalente:
(defn eager-fibonacci [a b]
(cons a (eager-fibonacci b (+' a b))))
(defn lazy-fibonacci [a b]
(lazy-seq (cons a (lazy-fibonacci b (+' a b)))))
Vectores
[]
;;=> []
[:foo]
;;=> [:foo]
[:foo :bar]
;;=> [:foo :bar]
[1 (+ 1 1) 3]
;;=> [1 2 3]
Además de usar la sintaxis literal, también puede usar la función vector para construir un vector:
https://riptutorial.com/es/home 27
(vector)
;;=> []
(vector :foo)
;;=> [:foo]
(vector 1 (+ 1 1) 3)
;;=> [1 2 3]
(vector? [])
;;=> true
(vector? nil)
;;=> false
(vector? 42)
;;=> false
(vector? :foo)
;;=> false
(conj [] :foo)
;;=> [:foo]
(count [])
;;=> 0
(peek [])
;;=> nil
https://riptutorial.com/es/home 28
(peek [:foo])
;;=> :foo
(pop [:foo])
;;=> []
(pop [])
;; java.lang.IllegalStateException: Can't pop empty vector
A diferencia de las listas, los vectores están indexados. Puede obtener un elemento de un vector
por índice en tiempo "constante" usando get :
Además, los vectores en sí mismos son funciones que toman un índice y devuelven el elemento
en ese índice:
([:foo :bar] 0)
;;=> :foo
([:foo :bar] 1)
;;=> :bar
Sin embargo, si llama a un vector con un índice no válido, obtendrá una IndexOutOfBoundsException
lugar de nil :
([:foo :bar] 2)
;; java.lang.IndexOutOfBoundsException:
https://riptutorial.com/es/home 29
Puede obtener un nuevo vector con un valor diferente en un índice particular usando assoc :
Si pasa un índice igual al count del vector, Clojure agregará el elemento como si hubiera usado
conj . Sin embargo, si pasa un índice que es negativo o mayor que el count , obtendrá una
IndexOutOfBoundsException :
(seq [])
;;=> nil
(seq [:foo])
;;=> (:foo)
Dado que los vectores están indexados, también puede obtener una secuencia invertida de los
elementos de un vector utilizando rseq :
(rseq [])
;;=> nil
(rseq [:foo])
;;=> (:foo)
Tenga en cuenta que, aunque todas las listas son secuencias, y las secuencias se muestran de la
misma manera que las listas, ¡no todas las secuencias son listas!
'(:foo :bar)
;;=> (:foo :bar)
https://riptutorial.com/es/home 30
;;=> true
Conjuntos
Al igual que los mapas, los conjuntos son asociativos y desordenados. A diferencia de los mapas,
que contienen asignaciones de claves a valores, los conjuntos se asignan esencialmente de las
claves a sí mismos.
#{}
;;=> #{}
#{:foo}
;;=> #{:foo}
#{:foo :bar}
;;=> #{:bar :foo}
Al igual que con los mapas, el orden en que aparecen los elementos en un conjunto literal no
importa:
(set? #{})
;;=> true
(set? #{:foo})
;;=> true
(set? nil)
;;=> false
(set? 42)
;;=> false
(set? :foo)
;;=> false
Puede probar si un mapa contiene un ítem dado en tiempo "constante" usando los contains?
predicado:
https://riptutorial.com/es/home 31
(contains? #{} :foo)
;;=> false
Además, los propios conjuntos son funciones que toman un elemento y devuelven ese elemento
si está presente en el conjunto, o nil si no lo está:
(#{} :foo)
;;=> nil
(#{:foo} :foo)
;;=> :foo
(#{:foo} :bar)
;;=> nil
(#{} nil)
;;=> nil
(#{nil} nil)
;;=> nil
Puede usar conj para obtener un conjunto que tenga todos los elementos de un conjunto
existente, más un elemento adicional:
Puede usar disj para obtener un conjunto que tenga todos los elementos de un conjunto
existente, menos un elemento:
https://riptutorial.com/es/home 32
(disj #{:foo :bar} :foo)
;;=> #{:bar}
(count #{})
;;=> 0
Puede obtener una secuencia de todos los elementos en un conjunto utilizando seq :
(seq #{})
;;=> nil
(seq #{:foo})
;;=> (:foo)
Mapas
A diferencia de la lista, que es una estructura de datos secuencial, y el vector, que es a la vez
secuencial y asociativo, el mapa es exclusivamente una estructura de datos asociativa. Un mapa
consiste en un conjunto de asignaciones de claves a valores. Todas las claves son únicas, por lo
que los mapas admiten la búsqueda en tiempo "constante" de las claves a los valores.
{}
;;=> {}
{:foo :bar}
;;=> {:foo :bar}
Cada par de dos elementos es un par clave-valor. Entonces, por ejemplo, el primer mapa de
arriba no tiene mapeos. El segundo tiene un mapeo, desde la clave :foo hasta el valor :bar . El
tercero tiene dos asignaciones, una de la clave :foo al valor :bar , y una de la clave :baz al valor
:qux . Los mapas están intrínsecamente desordenados, por lo que el orden en el que aparecen las
asignaciones no importa:
https://riptutorial.com/es/home 33
(= {:foo :bar :baz :qux}
{:baz :qux :foo :bar})
;;=> true
(map? {})
;;=> true
(map? nil)
;;=> false
(map? 42)
;;=> false
(map? :foo)
;;=> false
¿Puede probar si un mapa contiene una clave dada en tiempo "constante" usando los contains?
predicado:
https://riptutorial.com/es/home 34
;;=> nil
Además, los mapas en sí mismos son funciones que toman una clave y devuelven el valor
asociado con esa clave:
Puede obtener una entrada completa del mapa (clave y valor juntos) como un vector de dos
elementos usando find :
https://riptutorial.com/es/home 35
(find {:foo nil} :bar)
;;=> nil
Puede extraer la clave o el valor de una entrada de mapa usando key o val , respectivamente:
Tenga en cuenta que, aunque todas las entradas del mapa de Clojure son vectores, no todos los
vectores son entradas del mapa. Si intenta llamar a key o val en algo que no sea una entrada de
mapa, obtendrá una ClassCastException :
Puede usar assoc para obtener un mapa que tenga todos los mismos pares clave-valor que un
mapa existente, con un mapa agregado o modificado:
Puede usar dissoc para obtener un mapa que tenga todos los mismos pares clave-valor que un
mapa existente, con posiblemente un mapa eliminado:
https://riptutorial.com/es/home 36
(dissoc {:foo :bar :baz :qux} :foo)
;;=> {:baz :qux}
(count {})
;;=> 0
Puede obtener una secuencia de todas las entradas en un mapa usando seq :
(seq {})
;;=> nil
Nuevamente, los mapas no están ordenados, por lo que el orden de los elementos en una
secuencia que se obtiene al llamar a seq en un mapa no está definido.
Usted puede obtener una secuencia de sólo las teclas o sólo los valores en un mapa utilizando
keys o vals , respectivamente:
(keys {})
;;=> nil
(vals {})
;;=> nil
https://riptutorial.com/es/home 37
(vals {:foo :bar})
;;=> (:bar)
Clojure 1.9 agrega una sintaxis literal para representar de manera más concisa un mapa en el que
las claves comparten el mismo espacio de nombres. Tenga en cuenta que el mapa en cualquier
caso es idéntico (el mapa no "conoce" el espacio de nombres predeterminado), esto es
simplemente una conveniencia sintáctica.
https://riptutorial.com/es/home 38
Capítulo 8: Comenzando con el desarrollo
web
Examples
Crea una nueva aplicación de anillo con http-kit
Ring es una API estándar de facto para aplicaciones HTTP, similares a Ruby's Rack y al WSGI de
Python.
(ns test.core
(:gen-class)
(:require [org.httpkit.server :refer [run-server]]))
Definir controlador de solicitud de anillo. Los manejadores de solicitudes son solo funciones de
solicitud a respuesta y la respuesta es solo un mapa:
Aquí acabamos de devolver 200 OK con el mismo contenido para cualquier solicitud.
(defn -main
[& args]
(run-server app {:port 8080}))
https://riptutorial.com/es/home 39
Luminus es un micro-marco Clojure basado en un conjunto de bibliotecas ligeras. Su objetivo es
proporcionar una plataforma robusta, escalable y fácil de usar. Con Luminus, puedes concentrarte
en desarrollar tu aplicación de la manera que quieras sin distracciones. También tiene muy buena
documentación que cubre algunos de los principales temas.
Es muy fácil empezar con luminus. Solo crea un nuevo proyecto con los siguientes comandos:
Al ejecutar lein new luminus myapp se creará una aplicación utilizando la plantilla de perfil
predeterminada. Sin embargo, si desea adjuntar más funciones a su plantilla, puede agregar
sugerencias de perfil para la funcionalidad extendida.
Servidores web
• + aleph - agrega soporte del servidor Aleph al proyecto
• + embarcadero - agrega soporte de embarcadero al proyecto
• + http-kit - agrega el servidor web HTTP Kit al proyecto
bases de datos
• + h2: agrega las dependencias db.core namespace y H2 db
• + sqlite - agrega las dependencias db.core namespace y SQLite db
• + postgres: agrega el espacio de nombres db.core y agrega las dependencias de
PostreSQL
• + mysql: agrega el espacio de nombres db.core y agrega las dependencias de MySQL
• + mongodb - agrega las dependencias de espacio de nombres db.core y MongoDB
• + datomic - agrega espacio de nombres db.core y dependencias de Datomic
diverso
• + auth - agrega middleware de autenticación y dependencia de Buddy
• + auth-jwe: agrega la dependencia de Buddy con el backend de JWE
• + sidra - agrega soporte para CIDER usando el complemento CIDER nREPL
• + cljs - agrega soporte de [ClojureScript] [cljs] con reactivo
• + re-marco - añade [ClojureScript] [cljs] soporte con re-marco
• + pepino - un perfil para pepino con clj-webdriver
• + swagger - agrega soporte para Swagger-UI usando la biblioteca compojure-api
• + sassc - agrega soporte para archivos SASS / SCSS usando el compilador de línea de
comandos SassC
• + servicio: cree una aplicación de servicio sin la placa del final como las plantillas HTML
• + war: agregue el soporte para crear archivos WAR para su implementación en servidores
https://riptutorial.com/es/home 40
como Apache Tomcat (NO se debe usar para las aplicaciones Immutant que se ejecutan en
WildFly)
• + sitio: crea una plantilla para el sitio utilizando la base de datos especificada (H2 de forma
predeterminada) y ClojureScript
Para agregar un perfil, simplemente páselo como argumento después del nombre de su
aplicación, por ejemplo:
https://riptutorial.com/es/home 41
Capítulo 9: Configurando su entorno de
desarrollo
Examples
Mesa ligera
Light Table es un buen editor para aprender, experimentar y ejecutar proyectos de Clojure.
También puede ejecutar proyectos lein / boot abriendo el archivo project.clj . Se cargarán todas
las dependencias del proyecto.
Admite la evaluación en línea, los complementos y mucho más, por lo que no es necesario
agregar declaraciones de impresión y verificar el resultado en la consola. Puede ejecutar líneas
individuales o código blocska presionando ctrl + enter . Para ejecutar código parcial, seleccione
el código y presione ctrl + enter . consulte la siguiente captura de pantalla para saber cómo
puede usar Light Table para aprender y experimentar con el código Clojure.
https://riptutorial.com/es/home 42
tiene instalado Leiningen, instálelo siguiendo las instrucciones que se encuentran aquí .
Documentación: docs.lighttable.com
Emacs
Para configurar Emacs para trabajar con Clojure, instale clojure-mode y el paquete de cider de
melpa:
Ahora, cuando abra un archivo .clj , ejecute Mx cider-jack-in para conectarse a un REPL.
Alternativamente, puede usar Cu Mx (cider-jack-in) para especificar el nombre de un proyecto de
boot o de lein , sin tener que visitar ningún archivo en él. Ahora debería poder evaluar
expresiones en su archivo usando Cx Ce .
La edición de código en lenguajes similares a lisp es mucho más cómoda con un complemento de
edición con reconocimiento paren. Emacs tiene varias buenas opciones.
• pareditUn modo de edición de Lisp clásico que tiene una curva de aprendizaje más
pronunciada, pero que proporciona mucha potencia una vez que se domina.
• smartparensUn proyecto más nuevo con objetivos y uso similares para paredit , pero
también proporciona capacidades reducidas con lenguajes que no son Lisp.
• parinfer Un modo de edición de Lisp mucho más simple que funciona principalmente a
través de inferir el anidamiento correcto de la sangría.
Átomo
https://riptutorial.com/es/home 43
apm install parinfer
apm install language-clojure
apm install proto-repl
Después de reiniciar IDEA, Cursive debería estar trabajando fuera de la caja. Siga la guía del
usuario para ajustar la apariencia, las combinaciones de teclas, el estilo del código, etc.
Nota: al igual que IntelliJ , Cursive es un producto comercial, con un período de evaluación de
30 días. A diferencia de IntelliJ , no tiene una edición comunitaria. Las licencias gratuitas no
comerciales están disponibles para individuos para uso no comercial, incluyendo piratería
personal, código abierto y trabajo estudiantil. La licencia es válida por 6 meses y puede ser
renovada.
Spacemacs + SIDRA
Spacemacs es una distribución de emacs que viene con muchos paquetes preconfigurados y
fáciles de instalar. Además, es muy amigable para aquellos que están familiarizados con el estilo
de edición vim. Spacemacs proporciona una capa de Clojure basada en CIDER .
Para instalarlo y configurarlo para usarlo con Clojure, primero instale emacs. Luego haga una
copia de seguridad de sus configuraciones anteriores:
$ mv ~/.emacs.d ~/.emacs.d.backup
Ahora, abre emacs. Le hará algunas preguntas sobre sus preferencias. Luego descarga más
paquetes y configura tus emacs. Después de que se haya instalado Spacemacs, estará listo para
agregar el soporte de Clojure. Presione SPC fed para abrir su archivo .spacemacs para su
configuración. Encuentra dotspacemacs-configuration-layers en el archivo, debajo de él hay un
paren abierto. En cualquier lugar entre los parens en un nuevo tipo de línea clojure .
(defun dotspacemacs/layers ()
(setq-default
;; ...
dotspacemacs-configuration-layers
'(clojure
;; ...
)
;; ...
))
https://riptutorial.com/es/home 44
Presione SPC fe R para guardar e instalar la capa clojure. Ahora, en cualquier archivo .clj , si
presiona , si spacemacs intentará generar una nueva conexión REPL para su proyecto, y si tiene
éxito, se mostrará en la barra de estado, que luego puede presionar , ss para abrir un nuevo
búfer REPL Para evaluar tus códigos.
Para más información sobre spacemacs y sidra contacte sus documentaciones. Spacemacs docs
, documentos de sidra
Empuje
1. vim-clojure-static (si tiene un vim anterior a 7.3.803, las versiones más nuevas se envían
con este)
2. vim-clojure-highlight
https://riptutorial.com/es/home 45
Capítulo 10: core.async
Examples
Operaciones básicas del canal: crear, poner, tomar, cerrar y buffers.
core.async se trata de hacer procesos que tomen valores y pongan valores en canales .
Puede poner cualquier valor (cadenas, números, mapas, colecciones, objetos, incluso otros
canales, etc.) en un canal, excepto nil :
;; WON'T WORK
(a/>!! my-channel nil)
=> IllegalArgumentException Can't put nil on channel
Dependiendo del buffer del canal, >!! puede bloquear el hilo actual.
https://riptutorial.com/es/home 46
Desde el interior de un bloque (go ...) , puede y debe usar a/>! en lugar de a/>!! :
El comportamiento lógico será el mismo que a/>!! , pero solo se bloqueará el proceso lógico de
goroutine en lugar del hilo del sistema operativo real.
;; NEVER DO THIS
(a/go
(a/>!! ch :item))
;; creating a channel
(def ch (a/chan 3))
;; putting some items in it
(do
(a/>!! ch :item-1)
(a/>!! ch :item-2)
(a/>!! ch :item-3))
;; taking a value
(a/<!! ch) ;; => :item-1
(a/<!! ch) ;; => :item-2
Si no hay ningún elemento disponible en el canal, a/<!! bloqueará el hilo actual hasta que se
coloque un valor en el canal (o se cierre el canal, ver más adelante):
(def ch (a/chan))
(a/<!! ch) ;; blocks until another process puts something into ch or closes it
Desde el interior de un bloque (go ...) , puede y debe usar a/<! en lugar de a/<!! :
El comportamiento lógico será el mismo que a/<!! , pero solo se bloqueará el proceso lógico de
goroutine en lugar del hilo del sistema operativo real.
;; NEVER DO THIS
(a/go
(a/<!! ch))
Canales de cierre
https://riptutorial.com/es/home 47
Cierra un canal con a/close! :
(a/close! ch)
Una vez que se cierra un canal, y se han agotado todos los datos en el canal, las tomas siempre
devolverán nil :
;; taking from ch will return the items that were put in it, then nil
(a/<!! ch) ;; => :item-1
(a/<!! ch) ;; => :item-2
(a/<!! ch) ;; => nil
(a/<!! ch) ;; => nil
(a/<!! ch) ;; => nil
;; once the channel is closed, >!! will have no effect on the channel:
(a/>!! ch :item-3)
=> false ;; false means the put did not succeed
(a/<!! ch) ;; => nil
(a/put! ch :item)
(a/put! ch :item (fn once-put [closed?] ...)) ;; callback function, will receive
https://riptutorial.com/es/home 48
Ejemplo de búfer de caída:
https://riptutorial.com/es/home 49
Capítulo 11: Destrucción de clojure
Examples
Destructurando un vector
Entonces, por ejemplo dentro de un let bloque, puede extraer los valores del vector de manera
muy sucinta de la siguiente manera:
Destructurando un mapa
Luego, por ejemplo, dentro de un bloque Let puede extraer valores del mapa de manera muy
sucinta de la siguiente manera:
Observe que los valores que se extraen en cada asignación están a la izquierda y las claves con
las que están asociadas están a la derecha.
Si desea destruir valores en enlaces con los mismos nombres que las teclas, puede utilizar este
acceso directo:
https://riptutorial.com/es/home 50
Y de manera similar para los símbolos:
Si desea destruir un mapa anidado, puede anidar los formularios de enlace explicados
anteriormente:
(def data
{:foo {:a 1
:b 2}
:bar {:a 10
:b 20}})
Y desea extraer los primeros 3 elementos y obtener los elementos restantes como una secuencia.
Esto puede hacerse de la siguiente manera:
A veces desea destruir la clave debajo de un mapa que puede no estar presente en el mapa, pero
desea un valor predeterminado para el valor desestructurado. Puedes hacerlo de esta manera:
https://riptutorial.com/es/home 51
b :b
:keys [c d]
:or {a 1
c 2}} my-map]
(println a b c d))
;= 3 4 2 nil
La destrucción se realiza en muchos lugares, así como en la lista de parámetros de una fn:
(my-func [1 2 3]) ;= 5
(my-func (range 5)) ;= 3
(my-func2 1 2 3) ;= 5
(apply my-func2 (range 5)) ;= 3
(my-func 1 2) ;= 1 2 3 4
(my-func 3 4 :c 5 :d 6) ;= 3 4 5 6
Visión general
La destrucción le permite extraer datos de varios objetos en distintas variables. En cada ejemplo a
continuación, cada variable se asigna a su propia cadena ( a = "a" , b = "b" , & c.)
https://riptutorial.com/es/home 52
Tipo Ejemplo Valor de los data / comentario
vec anidado (let [[[ab] [cd]] data ...) [["a" "b"] ["c" "d"]]
- (let [{:keys [abc]} data Cuando las variables llevan el nombre de las
alternativa: ...) claves.
Consejos:
• Los valores predeterminados se pueden proporcionar utilizando :or , de lo contrario, el valor
predeterminado es nil
• Use & rest para almacenar una seq de valores extra en rest ; de lo contrario, los valores
adicionales se ignorarán
• Un uso común y útil de la desestructuración es para parámetros de función.
• Puede asignar partes no deseadas a una variable desechable (convencionalmente: _ )
aquí, la estructura de datos es bastante simple con solo 3 espacios (primer nombre , apellido,
país ), pero imagínese lo engorroso que sería si tuviéramos que repetir todos los nombres clave
dos veces para obtener una estructura de datos más granular (con mucho más espacio que solo
3) .
En su lugar, una mejor manera de manejar esto es mediante :keys (ya que nuestras claves son
palabras clave aquí) y seleccionando el nombre de la clave que nos gustaría vincular como así:
La misma lógica intuitiva se aplica a otros tipos de claves, como símbolos (con :syms ) y cadenas
simples y sin formato (con :strs )
https://riptutorial.com/es/home 53
;; using strings as keys
(def john {"lastname" "McCarthy" "firstname" "John" "country" "USA"})
;;#'user/john
(defn print-some-items
[[a b :as xs]]
(println a)
(println b)
(println xs))
(print-some-items [2 3])
2
3
[2 3]
https://riptutorial.com/es/home 54
Capítulo 12: Emacs CIDER
Introducción
CIDER es el acrónimo de C lojure (script) I nteractive D evelopment E am Environment que R
ocks. Es una extensión para emacs. CIDER tiene como objetivo proporcionar un entorno de
desarrollo interactivo para el programador. CIDER está construido sobre nREPL, un servidor
REPL en red y SLIME sirvió como la principal inspiración para CIDER.
Examples
Evaluación de la función
La función CIDER cider-eval-last-sexp puede usarse para ejecutar el código mientras se edita el
código dentro del búfer. Esta función está vinculada por defecto a Cx Ce o Cx Ce .
Por ejemplo:
(defn say-hello
[username]
(format "Hello, my name is %s" username))
(defn introducing-bob
[]
(say-hello "Bob")) => "Hello, my name is Bob"
Impresión bonita
Por ejemplo
https://riptutorial.com/es/home 55
(def databases {:database1 {:password "password"
:database "test"
:port "5432"
:host "localhost"
:user "username"}
(defn get-database-config
[]
databases)
(get-database-config)
Si ejecuta Cc mientras el cursor está justo delante del paréntesis final de la llamada a la función
Cp
get-database-config , se mostrará el mapa impreso en un nuevo búfer emergente.
{:database1
{:password "password",
:database "test",
:port "5432",
:host "localhost",
:user "username"},
:database2
{:password "password",
:database "different_test_db",
:port "5432",
:host "localhost",
:user "vader"}}
https://riptutorial.com/es/home 56
Capítulo 13: Enhebrar macros
Introducción
También conocidas como macros de flecha, las macros de subprocesamiento convierten
llamadas de función anidadas en un flujo lineal de llamadas de función.
Examples
Último hilo (- >>)
Esta macro da la salida de una línea dada como el último argumento de la siguiente llamada de
función de línea. Por ejemplo
es igual que
(->> 2
(+ 3)
(str)
(prn))
Esta macro da la salida de una línea dada como el primer argumento de la siguiente llamada de
función de línea. Por ejemplo
(-> {:a 1}
(assoc :b 1) ;;(assoc map key val)
(rename-keys {:b :new-b})) ;;(rename-keys map key-newkey-map)
Esta es una alternativa más flexible para subprocesar primero o subproceso último. Se puede
insertar en cualquier parte de la lista de parámetros de la función.
(as-> [1 2] x
(map #(+ 1 %) x)
(if (> (count x) 2) "Large" "Small"))
https://riptutorial.com/es/home 57
Lea Enhebrar macros en línea: https://riptutorial.com/es/clojure/topic/9582/enhebrar-macros
https://riptutorial.com/es/home 58
Capítulo 14: Funciones
Examples
Definiendo funciones
(defn welcome
"Return a welcome message to the world"
...)
(defn welcome
"Return a welcome message"
[name]
...)
(defn welcome
"Return a welcome message"
[name]
(str "Hello, " name "!"))
Llamándolo:
"Hello, World!"
Parámetros y Arity
(defn welcome
"Without parameters"
https://riptutorial.com/es/home 59
[]
"Hello!")
(defn square
"Take one parameter"
[x]
(* x x))
(defn multiplier
"Two parameters"
[x y]
(* x y))
Aridad
El número de argumentos que toma una función. Las funciones admiten la sobrecarga de arity , lo
que significa que las funciones en Clojure permiten más de un "conjunto" de argumentos.
(defn sum-args
;; 3 arguments
([x y z]
(+ x y z))
;; 2 arguments
([x y]
(+ x y))
;; 1 argument
([x]
(+ x 1)))
Las aridades no tienen que hacer el mismo trabajo, cada aridad puede hacer algo sin relación:
(defn do-something
;; 2 arguments
([first second]
(str first " " second))
;; 1 argument
([x]
(* x x x)))
Se puede definir una función de Clojure para tomar un número arbitrario de argumentos, usando
el símbolo y en su lista de argumentos. Todos los argumentos restantes se recogen como una
secuencia.
Vocación:
https://riptutorial.com/es/home 60
=> (sum 1 11 23 42)
77
Hay dos formas de definir una función anónima: la sintaxis completa y una taquigrafía.
(fn [x y] (+ x y))
Esta expresión se evalúa como una función. Cualquier sintaxis que pueda usar con una función
definida con defn ( & , desestructuración de argumentos, etc.), también puede hacer con la forma
fn . defn es en realidad una macro que solo hace (def (fn ...)) .
#(+ %1 %2)
Esta es la notación taquigráfica. Usando la notación abreviada, no tiene que nombrar argumentos
explícitamente; se les asignarán los nombres %1 , %2 , %3 y así sucesivamente de acuerdo con el
orden en que se pasaron. Si la función solo tiene un argumento, su argumento se llama solo % .
Sintaxis soportada
Puede utilizar varargs con funciones anónimas de la taquigrafía. Esto es completamente legal:
Toma un número variable de argumentos y devuelve verdadero si cada uno de ellos es par:
https://riptutorial.com/es/home 61
A pesar de la aparente contradicción, es posible escribir una función anónima con nombre
incluyendo un nombre, como en el siguiente ejemplo. Esto es especialmente útil si la función
necesita llamarse a sí misma pero también en los seguimientos de pila.
https://riptutorial.com/es/home 62
Capítulo 15: Interoperabilidad de Java
Sintaxis
• . te permite acceder a métodos de instancia
• .- permite acceder a campos de instancia
• .. macro expandiéndose a múltiples invocaciones anidadas de .
Observaciones
Como lenguaje alojado, Clojure proporciona un excelente soporte de interoperabilidad con Java.
El código Clojure también se puede llamar directamente desde Java.
Examples
Llamando a un método de instancia en un objeto Java
(.substring "hello" 0 2)
;;=> "he"
(java.awt.Point. 0 1)
;;=> => #object[java.awt.Point 0x3776d535 "java.awt.Point[x=0,y=1]"]
https://riptutorial.com/es/home 63
(new java.awt.Point 0 1)
;;=> => #object[java.awt.Point 0x3776d535 "java.awt.Point[x=0,y=1]"]
(System/currentTimeMillis)
;;=> 1469493415265
Puede llamar a una función Clojure desde el código Java buscando la función e invocándola:
Esto busca la función * desde el espacio de nombres clojure.core y la invoca con los argumentos
2 y 2.
https://riptutorial.com/es/home 64
Capítulo 16: La verdad
Examples
La verdad
Ejemplos:
Booleanos
Cualquier valor en Clojure se considera veraz a menos que sea false o nil . Puedes encontrar la
veracidad de un valor con (boolean value) . Puede encontrar la veracidad de una lista de valores
usando (or) , que devuelve true si algún argumento es verdadero, o (and) que devuelve true si
todos los argumentos son verdaderos.
https://riptutorial.com/es/home 65
Capítulo 17: Macros
Sintaxis
• El símbolo ' usado en el ejemplo de macroexpand es solo azúcar sintáctica para el
operador de quote . Podría haber escrito (macroexpand (quote (infix 1 + 2))) lugar.
Observaciones
Las macros son solo funciones que se ejecutan en tiempo de compilación, es decir, durante el
paso de eval en un ciclo de lectura-eval-print .
Las macros del lector son otra forma de macro que se expande en el momento de la lectura, en
lugar del tiempo de compilación.
Examples
Macro Infix simple
Clojure usa la notación de prefijo, es decir: el operador aparece antes que sus operandos.
(+ 1 2)
;; => 3
Las macros te permiten manipular el lenguaje de Clojure hasta cierto punto. Por ejemplo, podría
implementar una macro que le permita escribir código en notación de infijo (por ejemplo, 1 + 2 ):
• defmacro es una forma especial que se utiliza para definir una macro.
• infix es el nombre de la macro que estamos definiendo.
• [first-operand operator second-operand] son los parámetros que esta macro espera recibir
cuando se llama.
https://riptutorial.com/es/home 66
• (list operator first-operand second-operand) es el cuerpo de nuestra macro. Simplemente
crea una list con los valores de los parámetros proporcionados a la macro infix y los
devuelve.
defmacro es una forma especial porque se comporta de manera un poco diferente en comparación
con otras construcciones de Clojure: sus parámetros no se evalúan de inmediato (cuando
llamamos a la macro). Esto es lo que nos permite escribir algo como:
(infix 1 + 2)
;; => 3
La macro infix expandirá los argumentos 1 + 2 a (+ 1 2) , que es una forma de Clojure válida que
puede ser evaluada.
Si desea ver lo que genera la macro infix , puede usar el operador de macroexpand :
macroexpand , como lo macroexpand su nombre, expandirá la macro (en este caso, usará la macro
infix para transformar 1 + 2 en (+ 1 2) ) pero no permitirá que el resultado de la expansión de
macro sea evaluado por Intérprete de clojure
(defmacro and
"Evaluates exprs one at a time, from left to right. If a form
returns logical false (nil or false), and returns that value and
doesn't evaluate any of the other expressions, otherwise it returns
the value of the last expr. (and) returns true."
{:added "1.0"}
([] true)
([x] x)
([x & next]
`(let [and# ~x]
(if and# (and ~@next) and#))))
• llamado syntax-quote es como (quote) , pero recursivo: hace (let …) , (if …) , etc. no se
`
evalúa durante la expansión de macros sino que se genera como está
• ~ aka unquote cancela syntax-quote para una sola forma dentro de la forma sintaxis entre
comillas. Entonces, el valor de x se genera al expandir la macro (en lugar de mostrar el
símbolo x )
• ~@ aka unquote-splicing es como unquote pero toma el argumento de la lista y lo expande,
cada elemento de la lista se forma de forma separada
• # agrega una identificación única a los símbolos para evitar conflictos de nombre. Agrega la
misma ID para el mismo símbolo dentro de la expresión entre comillas de sintaxis, por lo
que and# dentro de let y and# inside if obtendremos el mismo nombre
https://riptutorial.com/es/home 67
Lea Macros en línea: https://riptutorial.com/es/clojure/topic/2322/macros
https://riptutorial.com/es/home 68
Capítulo 18: Operaciones de archivo
Examples
Visión general
(slurp "./small_file.txt")
(use 'clojure.java.io)
(with-open [rdr (reader "./file.txt")]
(line-seq rdr) ; returns lazy-seq
) ; with-open macro calls (.close rdr)
(use 'clojure.java.io)
(with-open [wrtr (writer "./log.txt" :append true)]
(.write wrtr "2016-07-26 New entry.")
) ; with-open macro calls (.close wrtr)
(use 'clojure.java.io)
(with-open [wrtr (writer "./file.txt")]
(.write wrtr "Everything in file.txt has been replaced with this text.")
) ; with-open macro calls (.close wrtr)
Notas:
• Puedes especificar URLs así como archivos
• Las opciones para (slurp) y (spit) se pasan a clojure.java.io/reader y /writer ,
respectivamente.
https://riptutorial.com/es/home 69
Capítulo 19: prueba de clojure
Examples
es
Puede agrupar aserciones relacionadas en las pruebas unitarias más deftest dentro de un
contexto usando la macro de testing :
(deftest add-nums
(testing "Positive cases"
(is (= 2 (+ 1 1)))
(is (= 4 (+ 2 2))))
(testing "Negative cases"
(is (= -1 (+ 2 -3)))
(is (= -4 (+ 8 -12)))))
Esto ayudará a aclarar la salida de prueba cuando se ejecuta. Tenga en cuenta que las testing
deben ocurrir dentro de un deftest .
deftestes una macro para definir una prueba de unidad, similar a las pruebas de unidad en otros
idiomas.
(deftest add-nums
(is (= 2 (+ 1 1)))
(is (= 3 (+ 1 2))))
https://riptutorial.com/es/home 70
Aquí estamos definiendo una prueba llamada add-nums , que prueba la función + . La prueba tiene
dos afirmaciones.
(run-tests)
O simplemente puede ejecutar las pruebas para el espacio de nombres en el que se encuentra la
prueba:
(run-tests 'your-ns)
son
Por ejemplo:
(are [x y] (= x y)
4 (+ 2 2)
8 (* 2 4))
=> true
Aquí, (= xy) actúa como una plantilla que tiene cada argumento y crea una is la afirmación de
ella.
(do
(is (= 4 (+ 2 2)))
(is (= 8 (* 2 4))))
Los accesorios son solo funciones que toman la función de prueba y la ejecutan con otros pasos
necesarios (antes / después, ajuste).
(ns myapp.test
(require [clojure.test :refer :all])
https://riptutorial.com/es/home 71
(use-fixtures :each stub-current-thing)
Cuando se usa con :once , envuelve toda la ejecución de pruebas en el espacio de nombres
actual con la función
Si está utilizando Leiningen y sus pruebas están ubicadas en el directorio de pruebas en la raíz de
su proyecto, entonces puede ejecutar sus pruebas utilizando la lein test
https://riptutorial.com/es/home 72
Capítulo 20: Realización de operaciones
matemáticas simples
Introducción
Así es como agregaría algunos números en la sintaxis de Clojure. Dado que el método aparece
como el primer argumento en la lista, estamos evaluando el método + (o adición) en el resto de
los argumentos en la lista.
Observaciones
Realizar operaciones matemáticas es la base para manipular datos y trabajar con listas. Por lo
tanto, entender cómo funciona es clave para progresar en la comprensión de Clojure.
Examples
Ejemplos de matematicas
;; returns 3
(+ 1 2)
;; returns 300
(+ 50 210 40)
;; returns 2
(/ 8 4)
https://riptutorial.com/es/home 73
Capítulo 21: tiempo de clj
Introducción
Este documento trata sobre cómo manipular la fecha y la hora en clojure.
Examples
Creando un tiempo de Joda
Obtención Día Mes Año Hora Minuto Segundo desde su fecha y hora
https://riptutorial.com/es/home 74
Comprobando si un tiempo está dentro de un intervalo de tiempo
Esta función indica si un tiempo dado se encuentra dentro de un intervalo de tiempo dado.
La función de intervalo que se usa es exclusiva , lo que significa que no incluye el segundo
argumento de la función dentro del intervalo. Como ejemplo:
La biblioteca clj-time.coerce puede ayudar a convertir otros formatos de fecha y hora al formato
de hora joda (clj-time.core / date-time). Los otros formatos incluyen formato largo de Java ,
cadena , fecha , fecha de SQL .
Para convertir el tiempo de otros formatos de tiempo, incluya la biblioteca y use la función from,
por ejemplo
cljs-time nos da la opción de agregar / restar fechas y horas a otras fechas y fechas. La fecha en
que se agregaron las restas debe ser en forma de días, meses, años, horas, etc.
;; Addition
(t/plus example-date (t/months 1)) ;; #<DateTime 2016-02-01T00:00:00.000Z>
(t/plus example-date (t/years 1)) ;; #<DateTime 2017-01-01T00:00:00.000Z>
https://riptutorial.com/es/home 75
;; Subtraction
(t/minus example-date (t/days 1)) ;; #<DateTime 2015-12-31T00:00:00.000Z>
(t/minus example-date (t/hours 12)) ;; #<DateTime 2015-12-31T12:00:00.000Z>
https://riptutorial.com/es/home 76
Capítulo 22: Transductores
Introducción
Los transductores son componentes componibles para procesar datos independientemente del
contexto. Por lo tanto, se pueden utilizar para procesar colecciones, flujos, canales, etc. sin
conocimiento de sus fuentes de entrada o receptores de salida.
La biblioteca central de Clojure se amplió en 1.7 para que la secuencia funcione como mapa,
filtro, toma, etc. devuelva un transductor cuando se le llame sin una secuencia. Debido a que los
transductores son funciones con contratos específicos, se pueden componer utilizando la función
de comp normal.
Observaciones
Los transductores permiten controlar la pereza a medida que se consumen. Por ejemplo into está
ansioso como sería de esperar, pero sequence perezosamente consumirá la secuencia a través del
transductor. Sin embargo, la garantía de pereza es diferente. Se consumirá suficiente de la fuente
para producir un elemento inicialmente:
(take 0 (sequence (comp (map #(do (prn '-> %) %)) (remove number?)) (range 5)))
;; -> 0
;; -> 1
;; -> 2
;; -> 3
;; -> 4
;; => ()
Examples
Pequeño transductor aplicado a un vector.
https://riptutorial.com/es/home 77
(transduce xf + [1 2 3 4 5 6 7 8 9 10]))
;; => 30
Este ejemplo crea un transductor asignado a la xf local y utiliza transduce para aplicarlo a algunos
datos. El transductor agrega uno a cada una de sus entradas y solo devuelve los números pares.
transduce es como reduce , y colapsa la colección de entrada a un solo valor usando la función +
provista.
Esto se lee como la macro del último hilo, pero separa los datos de entrada de los cálculos.
(->> [1 2 3 4 5 6 7 8 9 10]
(map inc)
(filter even?)
(reduce +))
;; => 30
Aplicando transductores
Cree un canal asíncrono central que use un transductor para filtrar mensajes:
Por lo tanto, las funciones más utilizadas en el mapa y el filtro de Clojure se han modificado para
devolver los transductores (transformaciones algorítmicas compuestas), si no se llaman con una
colección. Eso significa:
https://riptutorial.com/es/home 78
La ventaja: las funciones se pueden componer en una sola función por comp, lo que significa
atravesar la colección solo una vez. Ahorra tiempo de ejecución en más del 50% en algunos
escenarios.
Definición:
Uso:
;; We do this:
(into [] composed-fn [1 8 3 10 5])
;; Output: [9 11]
https://riptutorial.com/es/home 79
Capítulo 23: Vars
Sintaxis
• (valor del símbolo def)
• (def símbolo "docstring" valor)
• (declarar símbolo_0 símbolo_1 símbolo_2 ...)
Observaciones
Esto no debe confundirse con (defn) , que se utiliza para definir funciones.
Examples
Tipos de variables
• números
Tipos de números:
○ enteros
○ largos (números mayores que 2^31 - 1 )
○ flotadores (decimales)
• instrumentos de cuerda
• colecciones
Tipos de colecciones:
○ mapas
○ secuencias
○ vectores
• funciones
https://riptutorial.com/es/home 80
Creditos
S.
Capítulos Contributors
No
Analizando troncos
2 user2611740
con clojure
Coincidencia de
6 patrones con Kiran
core.match
Colecciones y
7 Alex Miller, Kenogu Labz, nXqd, Sam Estep
secuencias
Comenzando con el
8 Emin Tham, kolen, r00tt
desarrollo web
Interoperabilidad de
15 leeor
Java
https://riptutorial.com/es/home 81
17 Macros Alex Miller, kolen, mathk, Sam Estep, snowcrshd
Operaciones de
18 Zaz
archivo
Realización de
20 operaciones Jim
matemáticas simples
https://riptutorial.com/es/home 82