Seguimos con concurrencia en Clojure
Veamos un ejemplo que muestra cómo las estructuras de datos persistentes de Clojure significan que el estado mutable no puede escapar como lo hace en Java.
(def players (atom ()))
(defn list-players []
(response (json/encode @players)))
(defn create-player [player-name]
(swap! players conj player-name)
(status (response "") 201))
Esto define un par de rutas: una solicitud GET a /players recuperará una lista de los jugadores actuales (en formato JSON) y una solicitud PUT a "/players/:player-name" agregará un jugador a esa lista. El servidor Embedded Jetty es multiproceso, por lo que nuestro código deberá ser seguro para subprocesos.
Veámoslo en acción. Podemos ejecutarlo desde la línea de comandos con curl:
$ curl localhost:3000/players
[]
$ curl -X put localhost:3000/players/john
$ curl localhost:3000/players
["john"]
$ curl -X put localhost:3000/players/paul
$ curl -X put localhost:3000/players/george
$ curl -X put localhost:3000/players/ringo
$ curl localhost:3000/players
["ringo","george","paul","john"]
Todo esto parece muy simple (y lo es), pero algo podría estar preocupándote algo al respecto. Tanto las funciones de listar jugadores como las de crear jugadores acceden a los jugadores. ¿Por qué este código no sufre el mismo problema que el código Java? ¿Qué sucede si un subproceso agrega una entrada a la lista de reproductores mientras otro lo itera y lo convierte a JSON? Este código es seguro para subprocesos porque las estructuras de datos de Clojure son persistentes.
Y que significa que sea persistente? y en el próximo post te cuento.