| Clojure | ||
|---|---|---|
| Desarrollador(es) | ||
| Richard Hickey https://clojure.org/ | ||
| Información general | ||
| Extensiones comunes | clj, cljs, cljc, edn y cljr | |
| Paradigma | Funcional,Lenguaje de programación multiparadigma | |
| Apareció en | 2007 | |
| Diseñado por | Rich Hickey | |
| Última versión estable | (2022-03-22) | |
| Sistema de tipos | dinámico,fuerte | |
| Implementaciones | JVM,CLR, JavaScript | |
| Influido por | Lisp,ML,Haskell,ErlangProlog | |
| Sistema operativo | Multiplataforma | |
| Licencia | Eclipse Public License | |
Clojure es unlenguaje de programación de propósito general dialecto deLisp. Hace un énfasis especial en el paradigma funcional, con el objetivo (entre otros) de eliminar la complejidad asociada a laprogramación concurrente. Clojure puede ser ejecutado sobre laMáquina Virtual de Java y lamáquina virtual de la plataforma .NET, así como compilado aJavaScript.
Rich Hickey describe el desarrollo de Clojure como la búsqueda de un lenguaje que no pudo encontrar: un dialecto Lisp funcional por defecto, integrado sobre un entorno robusto en lugar de ser su propia plataforma, y con laprogramación concurrente en mente.[1]
Asimismo, en principio se rechaza la orientación a objetos, ofreciendo un enfoque en el que los programas se expresan como la aplicación de funciones sobre datos, más que como la interacción entre entidades mutables que mezclan representación de datos, y comportamiento. Por otra parte, características tales como instanciabilidad, polimorfismo e interfaces son efectivamente parte del lenguaje.
Como el resto de la familia Lisp, la sintaxis de Clojure está construida sobre expresiones simbólicas que son convertidas en estructuras de datos por unlector antes de ser compiladas. Las expresiones se caracterizan por estar delimitadas por paréntesis, y por su notación prefija, por la que se llama al primer miembro de cada lista como función, pasándole el resto de miembros como argumentos.
Esta peculiaridad, extraña para los habituados a los lenguajes más populares basados en la sintaxis dellenguaje de programación C es la base de su flexibilidad. Estructuras de datos tales comomapas,conjuntos yvectores tienen una expresión literal; no requieren transformación alguna a la hora de incorporarse al árbol sintáctico generado por el compilador. Clojure es unLisp-1 y no está particularmente diseñado para ser compatible con otros dialectos de Lisp.
Unmacro es un fragmento de código que acepta como argumentos otras expresiones, sin evaluar, transformándolas previamente a su evaluación. Esto permite la aparición de «programas que crean programas»: incorporaciones al lenguaje -estructuras de control de flujo- o creación de unlenguaje específico del dominio. Posibilidades en principio no alcanzables en otras familias de lenguajes sin recurrir al desarrollo de uncompilador.
El sistema de macros de Clojure es muy similar al deCommon Lisp con la excepción de que la versión de Clojure de la comilla inversa (llamada «comilla sintáctica») cualifica los símbolos con el espacio de nombres al que pertenece. Así se ayuda a prevenir la captura no intencionada ya que están prohibidos losbindings con nombres cualificados. Es posible forzar la expansión de una macro que las capture pero debe hacerse explícitamente. Clojure prohíbe también re-enlazar nombres globales en otros espacios de nombres que hayan sido importados en el actual.
Otra característica de la comilla sintáctica es que permite un sistema detemplating, en el que se puede especificar qué miembros de una lista deben evaluarse mediante los operadoresunquote (~) yunquote-splice (~@), dando lugar a macros más concisas y manejables.
Hola mundo. Nótese que dada la naturaleza del REPL, no es necesaria una orden deimpresión.
"¡Hola, mundo!"Un generador de números únicos y consecutivos que soporta llamadas concurrentes:
(let[i(atom0)](defngenerar-id-unica"Devuelve un identificador numérico distinto para cada llamada."[](swap!iinc)))
Una subclase anónima dejava.io.Writer que no escribe en ningún sitio y una macro que lo usa para silenciar todas las expresiones evaluadas con ella.
(defbit-bucket-writer(proxy[java.io.Writer][](write[buf]nil)(close[]nil)(flush[]nil)))(defmacronoprint"Evalua la expresiones dadas con todas las impresiones a *out* silenciadas."[&forms]`(binding[*out*bit-bucket-writer]~@forms))(noprint(println"Hello, nobody!"))
En este ejemplo diez hilos manipulan una estructura de datos compartida, que consiste en cien vectores que contienen diez números únicos al inicio secuenciales. Cada hilo elige dos posiciones aleatorias en dos vectores aleatorios y los intercambia. Todos los cambios en los vectores se hacen dentro de transacciones usando el sistema dememoria transaccional por software de Clojure. Es por eso que incluso después de mil iteraciones no se pierde ningún número.
(defnrun[nvecsnitemsnthreadsniters](let[vec-refs(vec(map(comprefvec)(partitionnitems(range(*nvecsnitems)))))swap#(let[v1(rand-intnvecs)v2(rand-intnvecs)i1(rand-intnitems)i2(rand-intnitems)](dosync(let[temp(nth@(vec-refsv1)i1)](alter(vec-refsv1)associ1(nth@(vec-refsv2)i2))(alter(vec-refsv2)associ2temp))))report#(do(prn(mapderefvec-refs))(println"Distinct:"(count(distinct(applyconcat(mapderefvec-refs))))))](report)(dorun(applypcalls(repeatnthreads#(dotimes[_niters](swap)))))(report)))(run1001010100000)
Salida del ejemplo anterior:
([0123456789][10111213141516171819]...[990991992993994995996997998999])Distinct:1000([382318466963619222127345596][80863980447139490495275289778]...[484216622139651592379228242355])Distinct:1000