Update translation

This commit is contained in:
Antonio Hernández Blas 2020-02-06 12:38:28 -06:00
parent 43cb521310
commit e60cd7ecdd
No known key found for this signature in database
GPG Key ID: 6EB1BAC2871D97B1

View File

@ -9,29 +9,30 @@ translators:
lang: es-es lang: es-es
--- ---
Clojure es un lenguaje de la familia Lisp desarrollado sobre la Máquina Virtual Clojure es un lenguaje de la familia Lisp desarrollado para la Máquina Virtual
de Java. Tiene un énfasis mayor en la de Java. Tiene un énfasis mayor en la
[programación funcional](https://es.wikipedia.org/wiki/Programación_funcional) [programación funcional](https://es.wikipedia.org/wiki/Programación_funcional)
pura que Common Lisp, pero incluyendo la posibilidad de usar pura que Common Lisp, pero incluye varias utilidades de
[SMT](https://es.wikipedia.org/wiki/Memoria_transacional) para manipular [SMT](https://es.wikipedia.org/wiki/Memoria_transacional) para manipular
el estado según se presente. el estado según se presente.
Esta combinación le permite gestionar la concurrencia de manera muy sencilla Esta combinación le permite gestionar el procesamiento concurrente de manera
y a menudo automáticamente. muy sencilla, y a menudo automáticamente.
(Necesitas la versión de Clojure 1.2 o reciente)
(Necesitas la versión de Clojure 1.2 o posterior)
```clojure ```clojure
; Los comentatios comienzan con punto y coma. ; Los comentarios comienzan con punto y coma.
; Clojure se escribe mediante "forms" (patrones), los cuales son ; Clojure se escribe mediante patrones ("forms"), los cuales son
; listas de objectos entre paréntesis, separados por espacios en blanco. ; listas de cosas entre paréntesis, separados por espacios en blanco.
; El "reader" (lector) de Clojure asume que el primer objeto es una ; El lector ("reader") de Clojure asume que la primera cosa es una
; función o una macro que se va a llamar, y que el resto son argumentos. ; función o una macro a llamar, y el resto son argumentos.
; El primer form en un archivo debe ser ns, para establecer el namespace ; La primera llamada en un archivo debe ser ns, para establecer el espacio de
; (espacio de nombres) ; nombres ("namespace")
(ns learnclojure) (ns learnclojure)
; Algunos ejemplos básicos: ; Algunos ejemplos básicos:
@ -52,69 +53,70 @@ y a menudo automáticamente.
; También es necesaria la negación para las operaciones lógicas ; También es necesaria la negación para las operaciones lógicas
(not true) ; => false (not true) ; => false
; Cuando se anidan Los patrones, estos funcionan de la manera esperada ; Los patrones anidados funcionan como esperas
(+ 1 (- 3 2)) ; = 1 + (3 - 2) => 2 (+ 1 (- 3 2)) ; = 1 + (3 - 2) => 2
; Tipos ; Tipos
;;;;;;;;;;;;; ;;;;;;;;;;;;;
; Clojure usa los tipos de objetos de Java para booleanos, strings (cadenas de ; Clojure usa los tipos de objetos de Java para booleanos, cadenas de
; caracteres) y números. ; caracteres ("strings") y números.
; Usa class para saber de qué tipo es. ; Usa class para inspeccionarlos.
(class 1); Los enteros son java.lang.Long por defecto (class 1); Los números enteros literales son java.lang.Long por defecto
(class 1.); Los numeros en coma flotante son java.lang.Double (class 1.); Los números en coma flotante literales son java.lang.Double
(class ""); Los strings van entre comillas dobles, y son (class ""); Los strings siempre van entre comillas dobles, y son
; son java.lang.String ; java.lang.String
(class false); Los Booleanos son java.lang.Boolean (class false); Los booleanos son java.lang.Boolean
(class nil); El valor "null" se escribe nil (class nil); El valor "null" se escribe nil
; Si quieres crear una lista de datos, precedela con una comilla ; Si quieres crear una lista literal de datos, usa ' para evitar su evaluación
; simple para evitar su evaluación
'(+ 1 2) ; => (+ 1 2) '(+ 1 2) ; => (+ 1 2)
; (que es una abreviatura de (quote (+ 1 2)) ) ; (que es una abreviatura de (quote (+ 1 2)))
; Puedes evaluar una lista precedida por comilla con eval ; Puedes evaluar una lista precedida por una comilla con eval
(eval '(+ 1 2)) ; => 3 (eval '(+ 1 2)) ; => 3
; Colecciones & Secuencias ; Colecciones & Secuencias
;;;;;;;;;;;;;;;;;;; ;;;;;;;;;;;;;;;;;;;
; Las Listas están basadas en las listas enlazadas, mientras que los Vectores ; Las Listas están basadas en listas enlazadas, mientras que los Vectores en
; en arrays. ; arreglos.
; Los Vectores y las Listas también son clases de Java! ; ¡Los Vectores y las Listas también son clases de Java!
(class [1 2 3]); => clojure.lang.PersistentVector (class [1 2 3]); => clojure.lang.PersistentVector
(class '(1 2 3)); => clojure.lang.PersistentList (class '(1 2 3)); => clojure.lang.PersistentList
; Una lista podría ser escrita como (1 2 3), pero debemos ponerle una ; Una lista podría ser escrita como (1 2 3), pero debemos precederle una
; comilla simple delante para evitar que el reader piense que es una función. ; comilla para evitar que el lector ("reader") piense que es una función.
; Además, (list 1 2 3) es lo mismo que '(1 2 3) ; Además, (list 1 2 3) es lo mismo que '(1 2 3)
; Las "Colecciones" son solo grupos de datos ; Las Colecciones ("collections") son solo grupos de datos
; Tanto las listas como los vectores son colecciones: ; Tanto las Listas como los Vectores son colecciones:
(coll? '(1 2 3)) ; => true (coll? '(1 2 3)) ; => true
(coll? [1 2 3]) ; => true (coll? [1 2 3]) ; => true
; Las "Secuencias" (seqs) son descripciones abstractas de listas de datos. ; Las Secuencias ("seqs") son descripciones abstractas de listas de datos.
; Solo las listas son seqs. ; Solo las listas son secuencias ("seqs").
(seq? '(1 2 3)) ; => true (seq? '(1 2 3)) ; => true
(seq? [1 2 3]) ; => false (seq? [1 2 3]) ; => false
; Una seq solo necesita proporcionar una entrada cuando es accedida. ; Una secuencia solo necesita proporcionar uno de sus elementos cuando es
; Así que, las seqs pueden ser perezosas -- pueden establecer series infinitas: ; accedido.
; Así que, las secuencias pueden ser perezosas -- pueden definir series
; infinitas:
(range 4) ; => (0 1 2 3) (range 4) ; => (0 1 2 3)
(range) ; => (0 1 2 3 4 ...) (una serie infinita) (range) ; => (0 1 2 3 4 ...) (una serie infinita)
(take 4 (range)) ; (0 1 2 3) (take 4 (range)) ; (0 1 2 3)
; Usa cons para agregar un elemento al inicio de una lista o vector ; Usa cons para agregar un elemento al inicio de una Lista o Vector
(cons 4 [1 2 3]) ; => (4 1 2 3) (cons 4 [1 2 3]) ; => (4 1 2 3)
(cons 4 '(1 2 3)) ; => (4 1 2 3) (cons 4 '(1 2 3)) ; => (4 1 2 3)
; conj agregará un elemento a una colección en la forma más eficiente. ; conj agregará un elemento a una colección en la forma más eficiente.
; Para listas, se añade al inicio. Para vectores, al final. ; Para Listas, se añade al inicio. Para vectores, al final.
(conj [1 2 3] 4) ; => [1 2 3 4] (conj [1 2 3] 4) ; => [1 2 3 4]
(conj '(1 2 3) 4) ; => (4 1 2 3) (conj '(1 2 3) 4) ; => (4 1 2 3)
; Usa concat para concatenar listas o vectores ; Usa concat para concatenar Listas o Vectores
(concat [1 2] '(3 4)) ; => (1 2 3 4) (concat [1 2] '(3 4)) ; => (1 2 3 4)
; Usa filter y map para actuar sobre colecciones ; Usa filter y map para actuar sobre colecciones
@ -126,7 +128,7 @@ y a menudo automáticamente.
; = (+ (+ (+ 1 2) 3) 4) ; = (+ (+ (+ 1 2) 3) 4)
; => 10 ; => 10
; reduce puede tener un argumento indicando su valor inicial. ; reduce puede tomar un argumento como su valor inicial también
(reduce conj [] '(3 2 1)) (reduce conj [] '(3 2 1))
; = (conj (conj (conj [] 3) 2) 1) ; = (conj (conj (conj [] 3) 2) 1)
; => [3 2 1] ; => [3 2 1]
@ -138,44 +140,42 @@ y a menudo automáticamente.
; su última expresión ; su última expresión
(fn [] "Hello World") ; => fn (fn [] "Hello World") ; => fn
; (Necesitas rodearlo con paréntesis para invocarla) ; (Necesitas rodearlo con paréntesis para llamarla)
((fn [] "Hello World")) ; => "Hello World" ((fn [] "Hello World")) ; => "Hello World"
; Puedes crear una var (variable) mediante def ; Puedes definir una variable ("var") mediante def
(def x 1) (def x 1)
x ; => 1 x ; => 1
; Asigna una función a una var ; Asignar una función a una variable ("var")
(def hello-world (fn [] "Hello World")) (def hello-world (fn [] "Hello World"))
(hello-world) ; => "Hello World" (hello-world) ; => "Hello World"
; Puedes defn como atajo para lo anterior ; Puedes usar defn como atajo para lo anterior
(defn hello-world [] "Hello World") (defn hello-world [] "Hello World")
; El [] es el vector de argumentos de la función. ; El [] es el Vector de argumentos de la función.
(defn hello [name] (defn hello [name]
(str "Hello " name)) (str "Hello " name))
(hello "Steve") ; => "Hello Steve" (hello "Steve") ; => "Hello Steve"
; Otra abreviatura para crear funciones es: ; Puedes usar esta abreviatura para definir funciones:
(def hello2 #(str "Hello " %1)) (def hello2 #(str "Hello " %1))
(hello2 "Fanny") ; => "Hello Fanny" (hello2 "Fanny") ; => "Hello Fanny"
; Puedes tener funciones multi-variadic: funciones con un numero variable de ; Puedes tener funciones multi-variables ("multi-variadic") también
; argumentos
(defn hello3 (defn hello3
([] "Hello World") ([] "Hello World")
([name] (str "Hello " name))) ([name] (str "Hello " name)))
(hello3 "Jake") ; => "Hello Jake" (hello3 "Jake") ; => "Hello Jake"
(hello3) ; => "Hello World" (hello3) ; => "Hello World"
; Las funciones pueden usar argumentos extras dentro de un seq utilizable en ; Las funciones pueden empaquetar argumentos extras en una secuencia para ti
; la función
(defn count-args [& args] (defn count-args [& args]
(str "You passed " (count args) " args: " args)) (str "You passed " (count args) " args: " args))
(count-args 1 2 3) ; => "You passed 3 args: (1 2 3)" (count-args 1 2 3) ; => "You passed 3 args: (1 2 3)"
; Y puedes mezclarlos con el resto de argumentos declarados de la función. ; Puedes combinar los argumentos regulares y los empaquetados
(defn hello-count [name & args] (defn hello-count [name & args]
(str "Hello " name ", you passed " (count args) " extra args")) (str "Hello " name ", you passed " (count args) " extra args"))
(hello-count "Finn" 1 2 3) (hello-count "Finn" 1 2 3)
@ -185,18 +185,18 @@ x ; => 1
; Mapas ; Mapas
;;;;;;;;;; ;;;;;;;;;;
; Mapas de Hash y mapas de arrays comparten una misma interfaz. Los mapas de ; Los Mapas de Hash ("HashMap") y Mapas de Arreglo ("ArrayMap") comparten una
; Hash tienen búsquedas más rápidas pero no mantienen el orden de las claves. ; interfaz. Los Mapas de Hash tienen búsquedas más rápidas pero no mantienen el
; orden de las llaves.
(class {:a 1 :b 2 :c 3}) ; => clojure.lang.PersistentArrayMap (class {:a 1 :b 2 :c 3}) ; => clojure.lang.PersistentArrayMap
(class (hash-map :a 1 :b 2 :c 3)) ; => clojure.lang.PersistentHashMap (class (hash-map :a 1 :b 2 :c 3)) ; => clojure.lang.PersistentHashMap
; Los mapas de arrays se convertidos en mapas de Hash en la mayoría de ; Los Mapas de Arreglo se convierten automáticamente en Mapas de Hash en la
; operaciones si crecen mucho, por lo que no debes preocuparte. ; mayoría de operaciones si crecen mucho, por lo que no debes preocuparte.
; Los mapas pueden usar cualquier tipo para sus claves, pero generalmente las ; Los Mapas pueden usar cualquier tipo para sus llaves, pero generalmente las
; keywords (palabras clave) son lo habitual. ; Claves ("keywords") son lo habitual.
; Las keywords son parecidas a cadenas de caracteres con algunas ventajas de ; Las Claves son como strings con algunas ventajas de eficiencia
; eficiencia
(class :a) ; => clojure.lang.Keyword (class :a) ; => clojure.lang.Keyword
(def stringmap {"a" 1, "b" 2, "c" 3}) (def stringmap {"a" 1, "b" 2, "c" 3})
@ -208,28 +208,28 @@ keymap ; => {:a 1, :c 3, :b 2}
; Por cierto, las comas son equivalentes a espacios en blanco y no hacen ; Por cierto, las comas son equivalentes a espacios en blanco y no hacen
; nada. ; nada.
; Recupera un valor de un mapa tratandolo como una función ; Recupera un valor de un Mapa tratándola como una función
(stringmap "a") ; => 1 (stringmap "a") ; => 1
(keymap :a) ; => 1 (keymap :a) ; => 1
; ¡Las keywords pueden ser usadas para recuperar su valor del mapa, también! ; ¡Las Claves pueden ser usadas para recuperar su valor del mapa, también!
(:b keymap) ; => 2 (:b keymap) ; => 2
; No lo intentes con strings. ; No lo intentes con strings.
;("a" stringmap) ;("a" stringmap)
; => Exception: java.lang.String cannot be cast to clojure.lang.IFn ; => Exception: java.lang.String cannot be cast to clojure.lang.IFn
; Si preguntamos por una clave que no existe nos devuelve nil ; Recuperando una clave no existente nos devuelve nil
(stringmap "d") ; => nil (stringmap "d") ; => nil
; Usa assoc para añadir nuevas claves a los mapas de Hash ; Usa assoc para añadir nuevas claves a los Mapas de Hash
(def newkeymap (assoc keymap :d 4)) (def newkeymap (assoc keymap :d 4))
newkeymap ; => {:a 1, :b 2, :c 3, :d 4} newkeymap ; => {:a 1, :b 2, :c 3, :d 4}
; Pero recuerda, ¡los tipos de Clojure son inmutables! ; Pero recuerda, ¡los tipos de Clojure son inmutables!
keymap ; => {:a 1, :b 2, :c 3} keymap ; => {:a 1, :b 2, :c 3}
; Usa dissoc para eliminar llaves ; Usa dissoc para eliminar claves
(dissoc keymap :a :b) ; => {:c 3} (dissoc keymap :a :b) ; => {:c 3}
; Conjuntos ; Conjuntos
@ -241,50 +241,86 @@ keymap ; => {:a 1, :b 2, :c 3}
; Añade un elemento con conj ; Añade un elemento con conj
(conj #{1 2 3} 4) ; => #{1 2 3 4} (conj #{1 2 3} 4) ; => #{1 2 3 4}
; Elimina elementos con disj ; Elimina uno con disj
(disj #{1 2 3} 1) ; => #{2 3} (disj #{1 2 3} 1) ; => #{2 3}
; Comprueba su existencia usando el conjunto como una función: ; Comprueba su existencia usando al Conjunto como una función:
(#{1 2 3} 1) ; => 1 (#{1 2 3} 1) ; => 1
(#{1 2 3} 4) ; => nil (#{1 2 3} 4) ; => nil
; Hay más funciones en el namespace clojure.sets ; Hay más funciones en el espacio de nombres clojure.sets
; Patrones útiles ; Patrones útiles
;;;;;;;;;;;;;;;;; ;;;;;;;;;;;;;;;;;
; Las construcciones lógicas en clojure son macros, y presentan el mismo ; Los operadores lógicos en clojure son solo macros, y presentan el mismo
; aspecto que el resto de forms. ; aspecto que el resto de patrones.
(if false "a" "b") ; => "b" (if false "a" "b") ; => "b"
(if false "a") ; => nil (if false "a") ; => nil
; Usa let para crear un binding (asociación) temporal ; Usa let para definir ("binding") una variable temporal
(let [a 1 b 2] (let [a 1 b 2]
(> a b)) ; => false (> a b)) ; => false
; Agrupa expresiones mediante do ; Agrupa sentencias mediante do
(do (do
(print "Hello") (print "Hello")
"World") ; => "World" (prints "Hello") "World") ; => "World" (prints "Hello")
; Las funciones tienen implicita la llamada a do ; Las funciones tienen un do implícito
(defn print-and-say-hello [name] (defn print-and-say-hello [name]
(print "Saying hello to " name) (print "Saying hello to " name)
(str "Hello " name)) (str "Hello " name))
(print-and-say-hello "Jeff") ;=> "Hello Jeff" (prints "Saying hello to Jeff") (print-and-say-hello "Jeff") ;=> "Hello Jeff" (prints "Saying hello to Jeff")
; Y el let también ; Y let también
(let [name "Urkel"] (let [name "Urkel"]
(print "Saying hello to " name) (print "Saying hello to " name)
(str "Hello " name)) ; => "Hello Urkel" (prints "Saying hello to Urkel") (str "Hello " name)) ; => "Hello Urkel" (prints "Saying hello to Urkel")
; Usa las macros de tubería ("threading", "arrow", "pipeline" o "chain")
; (-> y ->>) para expresar la transformación de datos de una manera más clara.
; La macro Tubería-primero ("Thread-first") (->) inserta en cada patrón el
; resultado de los previos, como el primer argumento (segundo elemento)
(->
{:a 1 :b 2}
(assoc :c 3) ;=> (assoc {:a 1 :b 2} :c 3)
(dissoc :b)) ;=> (dissoc (assoc {:a 1 :b 2} :c 3) :b)
; Esta expresión podría ser escrita como:
; (dissoc (assoc {:a 1 :b 2} :c 3) :b)
; y evalua a {:a 1 :c 3}
; La macro Tubería-último ("Thread-last") hace lo mismo, pero inserta el
; resultado de cada línea al *final* de cada patrón. Esto es útil para las
; operaciones de colecciones en particular:
(->>
(range 10)
(map inc) ;=> (map inc (range 10)
(filter odd?) ;=> (filter odd? (map inc (range 10))
(into [])) ;=> (into [] (filter odd? (map inc (range 10)))
; Result: [1 3 5 7 9]
; Cuando estés en una situación donde quieras tener más libertad en donde
; poner el resultado de transformaciones previas de datos en una expresión,
; puedes usar la macro as->. Con ella, puedes asignar un nombre especifico
; a la salida de la transformaciones y usarlo como identificador en tus
; expresiones encadenadas ("chain").
(as-> [1 2 3] input
(map inc input);=> You can use last transform's output at the last position
(nth input 2) ;=> and at the second position, in the same expression
(conj [4 5 6] input [8 9 10])) ;=> or in the middle !
; Módulos ; Módulos
;;;;;;;;;;;;;;; ;;;;;;;;;;;;;;;
; Usa use para obtener todas las funciones del módulo ; Usa use para obtener todas las funciones del módulo
(use 'clojure.set) (use 'clojure.set)
; Ahora podemos usar más operaciones de conjuntos ; Ahora podemos usar más operaciones de Conjuntos
(intersection #{1 2 3} #{2 3 4}) ; => #{2 3} (intersection #{1 2 3} #{2 3 4}) ; => #{2 3}
(difference #{1 2 3} #{2 3 4}) ; => #{1} (difference #{1 2 3} #{2 3 4}) ; => #{1}
@ -294,19 +330,18 @@ keymap ; => {:a 1, :b 2, :c 3}
; Usa require para importar un módulo ; Usa require para importar un módulo
(require 'clojure.string) (require 'clojure.string)
; Usa / para llamar a las funciones de un módulo ; Usa / para llamar las funciones de un módulo
; Aquí, el módulo es clojure.string y la función es blank? ; Aquí, el módulo es clojure.string y la función es blank?
(clojure.string/blank? "") ; => true (clojure.string/blank? "") ; => true
; Puedes asignarle una abreviatura a un modulo al importarlo ; Puedes asignarle una sobrenombre a un modulo al importarlo
(require '[clojure.string :as str]) (require '[clojure.string :as str])
(str/replace "This is a test." #"[a-o]" str/upper-case) ; => "THIs Is A tEst." (str/replace "This is a test." #"[a-o]" str/upper-case) ; => "THIs Is A tEst."
; (#"" es una expresión regular) ; (#"" es una expresión regular literal)
; Puedes usar require (y use, pero no lo hagas) desde un espacio de nombre ; Puedes usar require (y use, pero no lo hagas) desde un espacio de nombres
; usando :require, ; usando :require,
; No necesitas preceder con comilla simple tus módulos si lo haces de esta ; No necesitas preceder con comilla tus módulos si lo haces de esta manera.
; forma.
(ns test (ns test
(:require (:require
[clojure.string :as str] [clojure.string :as str]
@ -315,8 +350,8 @@ keymap ; => {:a 1, :b 2, :c 3}
; Java ; Java
;;;;;;;;;;;;;;;;; ;;;;;;;;;;;;;;;;;
; Java tiene una enorme librería estándar, por lo que resulta util ; Java tiene una enorme y útil librería estándar, por lo que querrás
; aprender como interactuar con ella. ; aprender como hacer uso de ella.
; Usa import para cargar un módulo de java ; Usa import para cargar un módulo de java
(import java.util.Date) (import java.util.Date)
@ -329,14 +364,15 @@ keymap ; => {:a 1, :b 2, :c 3}
; Usa el nombre de la clase con un "." al final para crear una nueva instancia ; Usa el nombre de la clase con un "." al final para crear una nueva instancia
(Date.) ; <un objeto Date> (Date.) ; <un objeto Date>
; Usa "." para llamar a métodos o usa el atajo ".método" ; Usa "." para llamar métodos. O, usa el atajo ".método"
(. (Date.) getTime) ; <un timestamp> (. (Date.) getTime) ; <un timestamp>
(.getTime (Date.)) ; exactamente la misma cosa (.getTime (Date.)) ; exactamente lo mismo.
; Usa / para llamar métodos estáticos. ; Usa / para llamar métodos estáticos.
(System/currentTimeMillis) ; <un timestamp> (System siempre está presente) (System/currentTimeMillis) ; <un timestamp> (System siempre está presente)
; Usa doto para hacer frente al uso de clases (mutables) más tolerable ; Usa doto para lidiar con el uso de clases (mutables) de una manera más
; tolerable
(import java.util.Calendar) (import java.util.Calendar)
(doto (Calendar/getInstance) (doto (Calendar/getInstance)
(.set 2000 1 1 0 0 0) (.set 2000 1 1 0 0 0)
@ -345,9 +381,9 @@ keymap ; => {:a 1, :b 2, :c 3}
; STM ; STM
;;;;;;;;;;;;;;;;; ;;;;;;;;;;;;;;;;;
; Software Transactional Memory es un mecanismo que usa clojure para gestionar ; La Memoria Transaccional ("Software Transactional Memory" / "STM") es un
; el estado persistente. Hay unas cuantas construcciones en clojure que ; mecanismo que usa clojure para gestionar la persistecia de estado. Hay unas
; hacen uso de este mecanismo. ; cuantas construcciones en clojure que hacen uso de él.
; Un atom es el más sencillo. Se le da un valor inicial ; Un atom es el más sencillo. Se le da un valor inicial
(def my-atom (atom {})) (def my-atom (atom {}))
@ -356,15 +392,15 @@ keymap ; => {:a 1, :b 2, :c 3}
; swap! toma una función y la llama con el valor actual del atom ; swap! toma una función y la llama con el valor actual del atom
; como su primer argumento, y cualquier argumento restante como el segundo ; como su primer argumento, y cualquier argumento restante como el segundo
(swap! my-atom assoc :a 1) ; Establece my-atom al resultado (swap! my-atom assoc :a 1) ; Establece my-atom al resultado
; de (assoc {} :a 1) ; de (assoc {} :a 1)
(swap! my-atom assoc :b 2) ; Establece my-atom al resultado (swap! my-atom assoc :b 2) ; Establece my-atom al resultado
; de (assoc {:a 1} :b 2) ; de (assoc {:a 1} :b 2)
; Usa '@' para no referenciar al atom sino para obtener su valor ; Usa '@' para no referenciar al atom y obtener su valor
my-atom ;=> Atom<#...> (Regresa el objeto Atom) my-atom ;=> Atom<#...> (Regresa el objeto Atom)
@my-atom ; => {:a 1 :b 2} @my-atom ; => {:a 1 :b 2}
; Un sencillo contador usando un atom sería ; Aquí está un sencillo contador usando un atom
(def counter (atom 0)) (def counter (atom 0))
(defn inc-counter [] (defn inc-counter []
(swap! counter inc)) (swap! counter inc))
@ -377,23 +413,25 @@ my-atom ;=> Atom<#...> (Regresa el objeto Atom)
@counter ; => 5 @counter ; => 5
; Otros forms que utilizan STM son refs y agents. ; Otras construcciones de STM son refs y agents.
; Refs: http://clojure.org/refs ; Refs: http://clojure.org/refs
; Agents: http://clojure.org/agents ; Agents: http://clojure.org/agents
```
### Lectura adicional ### Lectura adicional
Ésto queda lejos de ser exhaustivo, pero espero que sea suficiente para que Ésto queda lejos de ser exhaustivo, pero ojalá que sea suficiente para que
puedas empezar tu camino. puedas empezar tu camino.
Clojure.org tiene muchos artículos: Clojure.org tiene muchos artículos:
[http://clojure.org/](http://clojure.org/) [http://clojure.org](http://clojure.org)
Clojuredocs.org contiene documentación con ejemplos para la mayoría de Clojuredocs.org contiene documentación con ejemplos para la mayoría de
funciones principales (pertenecientes al core): funciones principales (pertenecientes al core):
[http://clojuredocs.org/quickref/Clojure%20Core](http://clojuredocs.org/quickref/Clojure%20Core) [http://clojuredocs.org/quickref](http://clojuredocs.org/quickref)
4Clojure es una genial forma de mejorar tus habilidades con clojure/FP: 4Clojure es una genial forma de mejorar tus habilidades con clojure/FP:
[http://www.4clojure.com/](http://www.4clojure.com/) [http://www.4clojure.com/](http://www.4clojure.com/)
Clojure-doc.org (, de verdad) tiene un buen número de artículos con los que iniciarse en Clojure: Clojure-doc.org (, de verdad) tiene un buen número de artículos con los que
[http://clojure-doc.org/](http://clojure-doc.org/) iniciarse en Clojure: [http://clojure-doc.org](http://clojure-doc.org)