Clojure - Guía rápida

Clojure es un lenguaje de programación funcional dinámico de alto nivel. Clojure está diseñado en base al lenguaje de programación LISP y tiene compiladores que lo hacen funcionar tanto en entornos de ejecución Java como .Net.

Antes de hablar sobre Clojure, vamos a tener una descripción rápida del lenguaje de programación LISP. Los LISP tienen un núcleo de lenguaje diminuto, casi sin sintaxis y una potente función de macros. Con estas características, puede doblar LISP para que se adapte a su diseño, en lugar de al revés. LISP existe desde hace mucho tiempo desde 1958.

Common LISP lee una expresión, la evalúa y luego imprime el resultado. Por ejemplo, si desea calcular el valor de una expresión matemática simple de 4 + 6, escriba.

USER(1) (+ 4 6)

Clojure tiene los siguientes objetivos clave de alto nivel como lenguaje de programación.

  • Se basa en el lenguaje de programación LISP que hace que sus declaraciones de código sean más pequeñas que los lenguajes de programación tradicionales.

  • Es un lenguaje de programación funcional.

  • Se centra en la inmutabilidad, que es básicamente el concepto de que no debe realizar ningún cambio en los objetos que se crean en su lugar.

  • Puede administrar el estado de una aplicación para el programador.

  • Es compatible con la concurrencia.

  • Abarca los lenguajes de programación existentes. Por ejemplo, Clojure puede hacer uso de todo el ecosistema de Java para la gestión de la ejecución del código a través de la JVM.

El sitio web oficial de Clojure es https://clojure.org/

Hay una variedad de formas de trabajar con Clojure como lenguaje de programación. Veremos dos formas de trabajar con la programación de Clojure.

  • Leiningen - Leiningen es una herramienta esencial para crear, construir y automatizar proyectos de Clojure.

  • Eclipse Plugin - Existe un complemento llamado CounterClockwise, que está disponible para Eclipse para llevar a cabo el desarrollo de Clojure en el IDE de Eclipse.

Instalación de Leiningen

Asegúrese de que se cumplan los siguientes requisitos del sistema antes de continuar con la instalación.

Requisitos del sistema

JDK JDK 1.7 o superior
Memoria 2 GB de RAM (recomendado)

Step 1- Descarga la instalación binaria. Ir al enlacehttp://leiningen-wininstallerpara obtener el instalador de Windows. Haga clic en la opción para iniciar la descarga del instalador Groovy.

Step 2 - Inicie el instalador y haga clic en el botón Siguiente.

Step 3 - Especifique la ubicación para la instalación y haga clic en el botón Siguiente.

Step 4- La configuración detectará la ubicación de una instalación de Java existente. Haga clic en el botón Siguiente para continuar.

Step 5 - Haga clic en el botón Instalar para comenzar la instalación.

Una vez completada la instalación, le dará la opción de abrir un Clojure REPL, que es un entorno que puede usarse para crear y probar sus programas Clojure.

Instalación de Eclipse

Asegúrese de que se cumplan los siguientes requisitos del sistema antes de continuar con la instalación.

Requisitos del sistema

JDK JDK 1.7 o superior
Eclipse Eclipse 4.5 (Marte)

Step 1- Abra Eclipse y haga clic en el elemento de Menú. Haga clic en Ayuda → Eclipse Marketplace.

Step 2- Escriba la palabra clave Clojure en el cuadro de diálogo que aparece y presione el botón 'Ir'. Aparecerá la opción para la izquierda, haga clic en el botón Instalar para comenzar la instalación de este complemento.

Step 3 - En el siguiente cuadro de diálogo, haga clic en el botón Confirmar para comenzar la instalación.

Step 4- En el siguiente cuadro de diálogo, se le pedirá que acepte el acuerdo de licencia. Acepte el acuerdo de licencia y haga clic en el botón Finalizar para continuar con la instalación.

La instalación comenzará y, una vez completada, le pedirá que reinicie Eclipse.

Una vez que se reinicia Eclipse, verá la opción en Eclipse para crear un nuevo proyecto de Clojure.

Para comprender la sintaxis básica de Clojure, veamos primero un programa simple de Hello World.

Hola mundo como programa completo

Escribe 'Hola mundo' en un programa Clojure completo. A continuación se muestra un ejemplo.

Ejemplo

(ns clojure.examples.hello
   (:gen-class))
(defn hello-world []
   (println "Hello World"))
(hello-world)

Se deben tener en cuenta las siguientes cosas sobre el programa anterior.

  • El programa se escribirá en un archivo llamado main.clj. La extensión 'clj' es el nombre de la extensión de un archivo de código clojure. En el ejemplo anterior, el nombre del archivo se llama main.clj.

  • La palabra clave 'defn' se usa para definir una función. Veremos las funciones en detalle en otro capítulo. Pero por ahora, sepa que estamos creando una función llamada helloworld, que tendrá nuestro código principal de Clojure.

  • En nuestro código de Clojure, estamos usando la declaración 'println' para imprimir "Hello World" en la salida de la consola.

  • Luego llamamos a la función hello-world que a su vez ejecuta la declaración 'println'.

El programa anterior produce la siguiente salida.

Salida

Hello World

Forma general de una declaración

La forma general de cualquier declaración debe evaluarse entre llaves, como se muestra en el siguiente ejemplo.

(+ 1 2)

En el ejemplo anterior, toda la expresión está entre llaves. La salida de la declaración anterior es 3. El operador + actúa como una función en Clojure, que se usa para la suma de números. Los valores de 1 y 2 se conocen como parameters to the function.

Consideremos otro ejemplo. En este ejemplo, 'str' es el operador que se usa para concatenar dos cadenas. Las cadenas "Hola" y "Mundo" se utilizan como parámetros.

(str "Hello" "World")

Ejemplo

Si combinamos las dos declaraciones anteriores y escribimos un programa, se verá así.

(ns clojure.examples.hello
   (:gen-class))
(defn Example []
   (println (str "Hello World"))
   (println (+ 1 2)))
(Example)

Salida

El programa anterior produce la siguiente salida.

Hello World
3

Espacios de nombres

Un espacio de nombres se utiliza para definir un límite lógico entre los módulos definidos en Clojure.

Espacio de nombres actual

Esto define el espacio de nombres actual en el que reside el código Clojure actual.

Sintaxis

*ns*

Ejemplo

En la ventana de comandos REPL, ejecute el siguiente comando.

*ns*

Salida

Cuando ejecutamos el comando anterior, la salida diferirá dependiendo de cuál sea el espacio de nombres actual. A continuación se muestra un ejemplo de una salida. El espacio de nombres del código Clojure es -

clojure.examples.hello

(ns clojure.examples.hello
   (:gen-class))
(defn Example []
   (println (str "Hello World"))
   (println (+ 1 2)))
(Example)

Requerir declaración en Clojure

El código de Clojure está empaquetado en bibliotecas. Cada biblioteca de Clojure pertenece a un espacio de nombres, que es análogo a un paquete de Java. Puede cargar una biblioteca Clojure con la declaración 'Requerir'.

Sintaxis

(require quoted-namespace-symbol)

Ejemplo

A continuación se muestra un ejemplo del uso de esta declaración.

(ns clojure.examples.hello
   (:gen-class))
(require ‘clojure.java.io’)
(defn Example []
   (.exists (file "Example.txt")))
(Example)

En el código anterior, estamos usando la palabra clave 'require' para importar el espacio de nombres clojure.java.io que tiene todas las funciones requeridas para la funcionalidad de entrada / salida. Como no tenemos la biblioteca requerida, podemos usar la función 'archivo' en el código anterior.

Comentarios en Clojure

Los comentarios se utilizan para documentar su código. Los comentarios de una sola línea se identifican mediante ;; en cualquier posición de la línea. A continuación se muestra un ejemplo.

Ejemplo

(ns clojure.examples.hello
   (:gen-class))

;; This program displays Hello World
(defn Example []
   (println "Hello World"))
(Example)

Delimitadores

En Clojure, las declaraciones se pueden dividir o delimitar mediante el uso de llaves curvas o corchetes.

Ejemplo

A continuación se muestran dos ejemplos.

(ns clojure.examples.hello
   (:gen-class))

;; This program displays Hello World
(defn Example []
   (println (+ 1 2 3)))
(Example)

Salida

El programa anterior produce la siguiente salida.

6

Ejemplo

A continuación se muestra otro ejemplo.

(ns clojure.examples.hello
   (:gen-class))

;; This program displays Hello World
(defn Example []
   (println [+ 1 2 3]))
(Example)

Salida

El programa anterior produce la siguiente salida.

[#object[clojure.core$_PLUS_ 0x10f163b "clojure.core$_PLUS_@10f163b"] 1 2 3]

Espacios en blanco

Los espacios en blanco se pueden usar en Clojure para dividir diferentes componentes de una declaración para mayor claridad. Esto se puede hacer con la ayuda del operador coma (,).

Por ejemplo, las siguientes dos declaraciones son equivalentes y la salida de ambas declaraciones será 15.

(+ 1 2 3 4 5)
(+ 1, 2, 3, 4, 5)

Aunque Clojure ignora las comas, a veces las usa para facilitar la lectura al programador.

Por ejemplo, si tiene un mapa hash como el siguiente (def a-map {: a 1: b 2: c 3}) y solicita su valor en la ventana REPL, Clojure imprimirá la salida como {: a 1, : b 2,: c 3}.

Los resultados son más fáciles de leer, especialmente si está mirando una gran cantidad de datos.

Simbolos

En Clojure, los símbolos son equivalentes a identificadores en otros lenguajes de programación. Pero a diferencia de otros lenguajes de programación, el compilador ve los símbolos como valores de cadena reales. Como un símbolo es un valor, un símbolo se puede almacenar en una colección, pasar como argumento a una función, etc., como cualquier otro objeto.

Un símbolo solo puede contener caracteres alfanuméricos y '* +! /. : - _? ' pero no debe comenzar con un número o dos puntos.

A continuación se muestran ejemplos válidos de símbolos.

tutorial-point!
TUTORIAL
+tutorial+

Estructura del proyecto Clojure

Por último, hablemos de una estructura de proyecto típica para un proyecto de Clojure. Dado que el código de Clojure se ejecuta en una máquina virtual Java, la mayor parte de la estructura del proyecto dentro de Clojure es similar a lo que encontraría en un proyecto Java. A continuación se muestra la instantánea de una estructura de proyecto de muestra en Eclipse para un proyecto de Clojure.

Es necesario tener en cuenta las siguientes cuestiones clave sobre la estructura del programa anterior.

  • demo_1: este es el paquete en el que se coloca el archivo de código Clojure.

  • core.clj: este es el archivo de código principal de Clojure, que contendrá el código para la aplicación Clojure.

  • La carpeta Leiningen contiene archivos como clojure-1.6.0.jar que son necesarios para ejecutar cualquier aplicación basada en Clojure.

  • El archivo pom.properties contendrá información como groupId, artifactId y la versión del proyecto Clojure.

  • El archivo project.clj contiene información sobre la propia aplicación Clojure. A continuación se muestra una muestra del contenido del archivo del proyecto.

(defproject demo-1 "0.1.0-SNAPSHOT"
   :description "FIXME: write description"
   :url "http://example.com/FIXME"
   :license {
      :name "Eclipse Public License"
      :url "http://www.eclipse.org/legal/epl-v10.html"
   }
   :dependencies [[org.clojure/clojure "1.6.0"]])

REPL (bucle de lectura-evaluación-impresión) es una herramienta para experimentar con el código Clojure. Le permite interactuar con un programa en ejecución y probar rápidamente si las cosas funcionan como deberían. Lo hace presentándole un mensaje en el que puede ingresar el código. Luego lee su entrada, la evalúa, imprime el resultado y se repite, presentándole un mensaje nuevamente.

Este proceso permite un ciclo de retroalimentación rápido que no es posible en la mayoría de los otros idiomas.

Inicio de una sesión REPL

Se puede iniciar una sesión REPL en Leiningen escribiendo el siguiente comando en la línea de comandos.

lein repl

Esto iniciará la siguiente ventana REPL.

Luego comienza a evaluar los comandos de Clojure en la ventana REPL según sea necesario.

Para iniciar una sesión REPL en Eclipse, haga clic en la opción Menú, vaya a Ejecutar como → Aplicación Clojure.

Esto iniciará una nueva sesión REPL en una ventana separada junto con la salida de la consola.

Conceptualmente, REPL es similar a Secure Shell (SSH). De la misma manera que puede usar SSH para interactuar con un servidor remoto, Clojure REPL le permite interactuar con un proceso Clojure en ejecución. Esta característica puede ser muy poderosa porque incluso puede adjuntar un REPL a una aplicación de producción en vivo y modificar su programa mientras se ejecuta.

Variables especiales en REPL

REPL incluye algunas variables útiles, la que se usa ampliamente es la variable especial * 1, * 2 y * 3. Se utilizan para evaluar los resultados de las tres expresiones más recientes.

El siguiente ejemplo muestra cómo se pueden utilizar estas variables.

user => "Hello"
Hello
user => "World"
World
user => (str *2 *1)
HelloWorld

En el ejemplo anterior, las dos primeras cadenas se envían a la ventana de salida de REPL como "Hola" y "Mundo", respectivamente. Luego, las variables * 2 y * 1 se utilizan para recuperar las últimas 2 expresiones evaluadas.

Clojure ofrece una amplia variedad de built-in data types.

Tipos de datos integrados

A continuación se muestra una lista de tipos de datos que se definen en Clojure.

  • Integers - A continuación se muestra la representación de los números enteros disponibles en Clojure.

    • Decimal Integers (Short, Long and Int)- Se utilizan para representar números enteros. Por ejemplo, 1234.

    • Octal Numbers- Se utilizan para representar números en representación octal. Por ejemplo, 012.

    • Hexadecimal Numbers- Se utilizan para representar números en representación. Por ejemplo, 0xff.

    • Radix Numbers- Se utilizan para representar números en representación de base. Por ejemplo, 2r1111 donde la base es un número entero entre 2 y 36, inclusive.

  • Floating point

    • El valor predeterminado se utiliza para representar números de coma flotante de 32 bits. Por ejemplo, 12.34.

    • La otra representación es la notación científica. Por ejemplo, 1.35e-12.

  • char- Esto define un solo carácter literal. Los caracteres se definen con el símbolo de reacción. Por ejemplo, / e.

  • Boolean - Esto representa un valor booleano, que puede ser verdadero o falso.

  • String- Son literales de texto que se representan en forma de cadena de caracteres. Por ejemplo, "Hola mundo".

  • Nil - Esto se usa para representar un valor NULL en Clojure.

  • Atom- Los átomos proporcionan una forma de gestionar el estado independiente, sincrónico y compartido. Son un tipo de referencia como refs y vars.

Valores vinculados

Dado que todos los tipos de datos en Clojure se heredan de Java, los valores delimitados son los mismos que en el lenguaje de programación Java. La siguiente tabla muestra los valores máximos permitidos para los literales numéricos y decimales.

literales Rangos
Corto -32.768 hasta 32.767
En t -2,147,483,648 a 2,147,483,647
largo -9,223,372,036,854,775,808 a +9,223,372,036,854,775,807
flotador 1.40129846432481707e-45 a 3.40282346638528860e + 38
doble 4.94065645841246544e-324d a 1.79769313486231570e + 308d

Tipos numéricos de clase

Además de los tipos primitivos, se permiten los siguientes tipos de objetos (a veces denominados tipos de envoltura).

Nombre
java.lang.Byte
java.lang.Short
java.lang.Integer
java.lang.Long
java.lang.Float
java.lang.Double

Ejemplo

El siguiente programa muestra un código clojure consolidado para demostrar los tipos de datos en Clojure.

(ns clojure.examples.hello
   (:gen-class))

;; This program displays Hello World
(defn Example []
   ;; The below code declares a integer variable
   (def x 1)
   
   ;; The below code declares a float variable
   (def y 1.25)
   
   ;; The below code declares a string variable
   (def str1 "Hello")
   (println x)
   (println y)
   (println str1))
(Example)

Salida

El programa anterior produce la siguiente salida.

1
1.25
Hello

En Clojure, variables están definidos por el ‘def’palabra clave. Es un poco diferente en el que el concepto de variables tiene más que ver con la vinculación. En Clojure, un valor está vinculado a una variable. Una cosa clave a tener en cuenta en Clojure es que las variables son inmutables, lo que significa que para que el valor de la variable cambie, debe destruirse y recrearse nuevamente.

Los siguientes son los tipos básicos de variables en Clojure.

  • short- Esto se usa para representar un número corto. Por ejemplo, 10.

  • int- Esto se usa para representar números enteros. Por ejemplo, 1234.

  • long- Esto se usa para representar un número largo. Por ejemplo, 10000090.

  • float- Se utiliza para representar números de coma flotante de 32 bits. Por ejemplo, 12.34.

  • char- Esto define un solo carácter literal. Por ejemplo, '/ a'.

  • Boolean - Esto representa un valor booleano, que puede ser verdadero o falso.

  • String- Son literales de texto que se representan en forma de cadena de caracteres. Por ejemplo, "Hola mundo".

Declaraciones de variables

A continuación se muestra la sintaxis general para definir una variable.

Sintaxis

(def var-name var-value)

Donde 'var-name' es el nombre de la variable y 'var-value' es el valor vinculado a la variable.

Ejemplo

A continuación se muestra un ejemplo de declaración de variable.

(ns clojure.examples.hello
   (:gen-class))

;; This program displays Hello World
(defn Example []
   ;; The below code declares a integer variable
   (def x 1)
   
   ;; The below code declares a float variable
   (def y 1.25)

   ;; The below code declares a string variable
   (def str1 "Hello")
   
   ;; The below code declares a boolean variable
   (def status true))
(Example)

Nombrar variables

El nombre de una variable puede estar compuesto por letras, dígitos y el carácter de subrayado. Debe comenzar con una letra o un guión bajo. Las letras mayúsculas y minúsculas son distintas porque Clojure, al igual que Java, es un lenguaje de programación que distingue entre mayúsculas y minúsculas.

Ejemplo

A continuación se muestran algunos ejemplos de nombres de variables en Clojure.

(ns clojure.examples.hello
   (:gen-class))

;; This program displays Hello World
(defn Example []
   ;; The below code declares a Boolean variable with the name of status
   (def status true)
   
   ;; The below code declares a Boolean variable with the name of STATUS
   (def STATUS false)
   
   ;; The below code declares a variable with an underscore character.
   (def _num1 2))
(Example)

Note - En las declaraciones anteriores, debido a la distinción entre mayúsculas y minúsculas, el estado y el ESTADO son dos variables diferentes definidas en Clojure.

El ejemplo anterior muestra cómo definir una variable con un carácter de subrayado.

Imprimir variables

Dado que Clojure usa el entorno JVM, también puede usar la función 'println'. El siguiente ejemplo muestra cómo se puede lograr esto.

Ejemplo

(ns clojure.examples.hello
   (:gen-class))

;; This program displays Hello World
(defn Example []
   ;; The below code declares a integer variable
   (def x 1)
   
   ;; The below code declares a float variable
   (def y 1.25)
   
   ;; The below code declares a string variable
   (def str1 "Hello")
   (println x)
   (println y)
   (println str1))
(Example)

Salida

El programa anterior produce la siguiente salida.

1
1.25
Hello

Un operator es un símbolo que le dice al compilador que realice manipulaciones matemáticas o lógicas específicas.

Clojure tiene los siguientes tipos de operadores:

  • Operadores aritméticos
  • Operadores relacionales
  • Operadores logicos
  • Operadores bit a bit

Note - En Clojure, los operadores y operandos funcionan con la siguiente sintaxis.

Sintaxis

(operator operand1 operand2 operandn)

Por ejemplo,

Ejemplo

(+ 1 2)

El ejemplo anterior realiza una operación aritmética con los números 1 y 2.

Operadores aritméticos

El lenguaje Clojure admite los operadores aritméticos normales como cualquier lenguaje. A continuación se muestran los operadores aritméticos disponibles en Clojure.

Mostrar ejemplos

Operador Descripción Ejemplo
+ Adición de dos operandos (+ 1 2) dará 3
- Resta el segundo operando del primero (- 2 1) dará 1
* Multiplicación de ambos operandos (* 2 2) dará 4
/ División de numerador por denominador (float (/ 3 2)) dará 1,5
C ª Operadores incrementales utilizados para incrementar el valor de un operando en 1 inc 5 dará 6
dic Operadores incrementales utilizados para disminuir el valor de un operando en 1 5 de diciembre dará 4
max Devuelve el mayor de sus argumentos. max 1 2 3 devolverá 3
min Devuelve el menor de sus argumentos. min 1 2 3 devolverá 1
movimiento rápido del ojo Resto de dividir el primer número por el segundo rem 3 2 dará 1

Operadores relacionales

Los operadores relacionales permiten la comparación de objetos. A continuación se muestran los operadores relacionales disponibles en Clojure.

Mostrar ejemplos

Operador Descripción Ejemplo
= Prueba la igualdad entre dos objetos (= 2 2) dará verdadero
no = Prueba la diferencia entre dos objetos (no = 3 2) dará verdadero
< Comprueba si el objeto izquierdo es menor que el operando derecho (<2 3) dará verdadero
<= Comprueba si el objeto izquierdo es menor o igual que el operando derecho (<= 2 3) dará verdadero
> Comprueba si el objeto izquierdo es mayor que el operando derecho (> 3 2) dará verdadero
> = Comprueba si el objeto izquierdo es mayor o igual que el operando derecho (> = 3 2) dará verdadero

Operadores logicos

Los operadores lógicos se utilizan para evaluar expresiones booleanas. A continuación se muestran los operadores lógicos disponibles en Groovy.

Mostrar ejemplos

Operador Descripción Ejemplo
and Este es el operador lógico "y" (o verdadero verdadero) dará verdadero
or Este es el operador lógico "o" (y verdadero falso) dará falso
not Este es el operador lógico "no" (no falso) dará verdadero

El siguiente fragmento de código muestra cómo se pueden utilizar los distintos operadores.

Operadores bit a bit

Clojure proporciona cuatro operadores bit a bit. A continuación se muestran los operadores bit a bit disponibles en Clojure.

Mostrar ejemplos

No Señor. Operador y descripción
1

bit-and

Este es el operador "y" bit a bit

2

bit-or

Este es el operador "o" bit a bit

3

bit-xor

Este es el operador "xor" o exclusivo "or" bit a bit

4

bit-not

Este es el operador de negación bit a bit

A continuación se muestra la tabla de verdad que muestra estos operadores.

pags q p & q p | q p ^ q
0 0 0 0 0
0 1 0 1 1
1 1 1 1 0
1 0 0 1 1

Prioridad del operador

Como es el caso de los LISP en general, no hay necesidad de preocuparse por la precedencia de los operadores. Este es uno de los beneficios de las expresiones S y la notación de prefijo. Todas las funciones evalúan de izquierda a derecha y de adentro hacia afuera. Los operadores en Clojure son solo funciones, y todo está entre paréntesis.

Hasta ahora hemos visto sentencias que se ejecutan una tras otra de forma secuencial. Además, se proporcionan declaraciones en Clojure para alterar el flujo de control en la lógica de un programa. Luego se clasifican en declaraciones de flujo de control que veremos en detalle.

No Señor. Bucles y descripción
1 Mientras que la declaración

los 'while' La instrucción se ejecuta evaluando primero la expresión de condición (un valor booleano), y si el resultado es verdadero, entonces se ejecutan las instrucciones en el ciclo while.

2 Declaración de Doseq

los ‘doseq’declaración es similar a la declaración 'para cada' que se encuentra en muchos otros lenguajes de programación. La declaración doseq se utiliza básicamente para iterar sobre una secuencia.

3 Declaración de Dotimes

los ‘dotimes’ instrucción se utiliza para ejecutar una instrucción 'x' número de veces.

4 Declaración de bucle

La forma especial de bucle no es como un ‘for’lazo. El uso de loop es el mismo que el enlace let. Sin embargo, el bucle establece un punto de recursividad

Decision-making structures requerir que el programador especifique una o más condiciones para ser evaluadas o probadas por el programa, junto con una declaración o declaraciones que se ejecutarán si se determina que la condición es verdadera y, opcionalmente, otras declaraciones que se ejecutarán si se determina que ser falso.

No Señor. Métodos y descripción
1 Si declaración

En Clojure, la condición es una expresión que la evalúa como verdadera o falsa. 'If' la condición es verdadera, entonces se ejecutará la sentencia # 1, de lo contrario se ejecutará la sentencia # 2.

2 Si / hago expresión

los ‘if-do’ La expresión en Clojure se usa para permitir que se ejecuten múltiples expresiones para cada rama de la declaración 'if'.

3 Declaración If anidada

Múltiple 'if' declaraciones incrustadas una dentro de la otra.

4 Declaración de caso

Clojure ofrece la ‘case’ declaración que es similar a la ‘switch’ declaración disponible en el lenguaje de programación Java.

5 Declaración Cond

Clojure ofrece otra declaración de evaluación llamada ‘cond’declaración. Esta declaración toma un conjunto de pares de prueba / expresión.

Clojure es conocido como un lenguaje de programación funcional, por lo tanto, esperaría ver mucho énfasis en cómo funcionan las funciones en Clojure. Este capítulo cubre todo lo que se puede hacer con las funciones en Clojure.

No Señor. Funciones y descripción
1 Definición de una función

Una función se define mediante el ‘defn’ macro.

2 Funciones anónimas

Una función anónima es una función que no tiene un nombre asociado.

3 Funciones con múltiples argumentos

Las funciones de Clojure se pueden definir con cero o más parámetros. Los valores que pasa a las funciones se llamanargumentsy los argumentos pueden ser de cualquier tipo.

4 Funciones variadas

Clojure ofrece la declaración 'case' que es similar a la declaración 'switch' disponible en el lenguaje de programación Java.

5 Funciones de orden superior

Las funciones de orden superior (HOF) son funciones que toman otras funciones como argumentos. Los HOF son una técnica de programación funcional importante y se usan con bastante frecuencia en Clojure.

Numbers El tipo de datos en Clojure se deriva de las clases de Java.

Clojure admite números enteros y de punto flotante.

  • Un número entero es un valor que no incluye una fracción.

  • Un número de coma flotante es un valor decimal que incluye una fracción decimal.

A continuación se muestra un ejemplo de números en Clojure.

(def x 5)
(def y 5.25)

Donde 'x' es del tipo Integer y 'y' es el float.

En Java, las siguientes clases se adjuntan a los números definidos en Clojure.

Para ver realmente que los números en Clojure se derivan de las clases de Java, use el siguiente programa para ver el tipo de números asignados cuando usa el comando 'def'.

Ejemplo

(ns clojure.examples.hello
   (:gen-class))

;; This program displays Hello World
(defn Example []
   (def x 5)
   (def y 5.25)
   (println (type x))
   (println (type y)))
(Example)

los ‘type’ El comando se usa para generar la clase asociada con el valor asignado a una variable.

Salida

El código anterior producirá el siguiente resultado.

Java.lang.long
Java.lang.double

Pruebas numéricas

Las siguientes funciones de prueba están disponibles para números.

No Señor. Números y descripción
1 ¿cero?

Devuelve verdadero si el número es cero, de lo contrario falso.

2 pos?

Devuelve verdadero si el número es mayor que cero, de lo contrario falso.

3 neg?

Devuelve verdadero si el número es menor que cero, de lo contrario falso.

4 ¿incluso?

Devuelve verdadero si el número es par y genera una excepción si el número no es un entero.

5 ¿impar?

Devuelve verdadero si el número es impar y lanza una excepción si el número no es un entero.

6 ¿número?

Devuelve verdadero si el número es realmente un Número.

7 ¿entero?

Devuelve verdadero si el número es un entero.

8 ¿flotador?

Devuelve verdadero si el número es flotante.

Hemos visto la declaración recur en un tema anterior y mientras que el ciclo 'for' es algo así como un ciclo, recur es un bucle real en Clojure.

Si tiene experiencia en programación, es posible que haya oído hablar de la recursividad de cola, que es una característica importante de los lenguajes funcionales. Esta forma especial recurrente es la que implementa la recursividad de cola. Como indica la palabra "recursividad de cola", se debe llamar a recur en la posición de cola. En otras palabras, recur debe ser lo último en evaluarse.

El ejemplo más simple de la instrucción recur se usa dentro del ciclo 'for'. En el siguiente ejemplo, la instrucción recur se utiliza para cambiar el valor de la variable 'i' y devolver el valor de la variable a la expresión del ciclo.

Ejemplo

(ns clojure.examples.hello
   (:gen-class))

;; This program displays Hello World
(defn Example []
   (loop [i 0]
      (when (< i 5)
      (println i)
      (recur (inc i)))))
(Example)

Salida

El programa anterior produce la siguiente salida.

0
1
2
3
4

Clojure proporciona una serie de métodos auxiliares cuando se trabaja con E / S. Ofrece clases más fáciles para proporcionar las siguientes funcionalidades para archivos.

  • Leyendo archivos
  • Escribir en archivos
  • Ver si un archivo es un archivo o un directorio

Exploremos algunas de las operaciones de archivo que ofrece Clojure.

Leer el contenido de un archivo como una cadena completa

Si desea obtener todo el contenido del archivo como una cadena, puede utilizar la clojure.core.slurpmétodo. El comando slurp abre un lector en un archivo y lee todo su contenido, devolviendo una cadena.

A continuación se muestra un ejemplo de cómo se puede hacer esto.

(ns clojure.examples.hello
   (:gen-class))

;; This program displays Hello World
(defn Example []
   (def string1 (slurp "Example.txt"))
   (println string1))
(Example)

Si el archivo contiene las siguientes líneas, se imprimirán como:

line : Example1
line : Example2

Leer el contenido de un archivo una línea a la vez

Si desea obtener todo el contenido del archivo como una cadena, una línea a la vez, puede utilizar el clojure.java.io/readermétodo. La clase clojure.java.io/reader crea un búfer de lectura, que se utiliza para leer cada línea del archivo.

A continuación se muestra un ejemplo que muestra cómo se puede hacer esto.

(ns clojure.examples.hello
   (:gen-class))

;; This program displays Hello World
(defn Example []
   (with-open [rdr (clojure.java.io/reader "Example.txt")]
   (reduce conj [] (line-seq rdr))))
(Example)

Si el archivo contiene las siguientes líneas, se imprimirán como:

line : Example1
line : Example2

La salida se mostrará como -

["line : Example1" "line : Example2"]

Escribir archivos 'en'

Si desea escribir archivos 'en', puede usar el clojure.core.spitcomando para arrojar cadenas enteras en archivos. El comando de escupir es lo opuesto al método de sorber. Este método abre un archivo como escritor, escribe contenido y luego cierra el archivo.

A continuación se muestra un ejemplo.

(ns clojure.examples.hello
   (:gen-class))

;; This program displays Hello World
(defn Example []
   (spit "Example.txt"
      "This is a string"))

En el ejemplo anterior, si ve el contenido del archivo Example.txt, verá el contenido de "Esto es una cadena".

Escribir archivos 'en' una línea a la vez

Si desea escribir archivos 'a' una línea a la vez, puede usar el clojure.java.io.writerclase. La clase clojure.java.io.writer se utiliza para crear un flujo de escritura en el que los bytes de datos se introducen en el flujo y, posteriormente, en el archivo.

A continuación se muestra un ejemplo que muestra cómo se puede utilizar el comando spit.

(ns clojure.examples.hello
   (:gen-class))

;; This program displays Hello World
(defn Example []
   (with-open [w (clojure.java.io/writer "Example.txt" :append true)]
      (.write w (str "hello" "world"))))
(Example)

Cuando se ejecuta el código anterior, la línea "hola mundo" estará presente en el archivo Example.txt. La opción append: true es agregar datos al archivo. Si no se especifica esta opción, el archivo se sobrescribirá siempre que se escriban datos en el archivo.

Comprobación para ver si existe un archivo

Para comprobar si existe un archivo, clojure.java.io.fileLa clase se puede usar para verificar la existencia de un archivo. A continuación se muestra un ejemplo que muestra cómo se puede lograr esto.

(ns clojure.examples.hello
   (:gen-class))

;; This program displays Hello World
(defn Example []
   (println (.exists (clojure.java.io/file "Example.txt"))))
(Example)

Si existe el archivo Example.txt, la salida será verdadera.

Leyendo desde la consola

Para leer datos de la consola, el read-linese puede utilizar una declaración. A continuación se muestra un ejemplo que muestra cómo se puede utilizar.

Si ingresa el comando (línea de lectura) en la ventana REPL, tendrá la oportunidad de ingresar alguna entrada en la ventana de la consola.

user->(read-line)
Hello World

El código anterior producirá el siguiente resultado.

“Hello World”

UN Stringliteral se construye en Clojure encerrando el texto de la cadena entre comillas. Las cadenas en Clojure deben construirse utilizando comillas dobles como "Hola mundo".

Ejemplo

A continuación se muestra un ejemplo del uso de cadenas en Clojure.

(ns clojure.examples.hello
   (:gen-class))
(defn hello-world []
   (println "Hello World")
   (println "This is a demo application"))
(hello-world)

Salida

El programa anterior produce la siguiente salida.

Hello World
This is a demo application

Operaciones básicas con cadenas

Clojure tiene una serie de operaciones que se pueden realizar en cadenas. Las siguientes son las operaciones.

No Señor. Operaciones y descripción de cadenas
1 str

La concatenación de cadenas se puede realizar mediante la función str simple.

2 formato

El formateo de cadenas se puede realizar mediante la función de formato simple. La función de formato formatea una cadena usandojava.lang.String.format.

3 contar

Devuelve el número de caracteres de la cadena.

4 subs

Devuelve la subcadena de 's' que comienza al inicio inclusive y termina al final (por defecto es la longitud de la cadena), exclusiva.

5 comparar

Devuelve un número negativo, cero o un número positivo cuando 'x' es lógicamente 'menor que', 'igual a' o 'mayor que' 'y'.

6 minúscula

Convierte cadenas a minúsculas.

7 mayúscula

Convierte la cadena en mayúsculas.

8 unirse

Devuelve una cadena de todos los elementos de la colección, como los devuelve (colección seq), separados por un separador opcional.

9 división

Divide la cadena en una expresión regular.

10 líneas divididas

Las cadenas divididas se basan en los caracteres de escape \ n o \ r \ n.

11 contrarrestar

Invierte los caracteres en una cadena.

12 reemplazar

Reemplaza todas las instancias de una coincidencia en una cadena con la cadena de reemplazo.

13 podar

Elimina los espacios en blanco de ambos extremos de la cuerda.

14 triml

Elimina los espacios en blanco del lado izquierdo de la cuerda.

15 trimr

Elimina los espacios en blanco del lado derecho de la cuerda.

Listes una estructura utilizada para almacenar una colección de elementos de datos. En Clojure, la Lista implementa elISeqinterfaz. Las listas se crean en Clojure usando la función de lista.

Ejemplo

A continuación se muestra un ejemplo de cómo crear una lista de números en Clojure.

(ns clojure.examples.example
   (:gen-class))
(defn example []
   (println (list 1 2 3 4)))
(example)

Salida

El código anterior produce la siguiente salida.

(1 2 3 4)

A continuación se muestra un ejemplo de cómo crear una lista de personajes en Clojure.

(ns clojure.examples.example
   (:gen-class))
(defn example []
   (println (list 'a 'b 'c 'd)))
(example)

El código anterior produce la siguiente salida.

(a b c d)

A continuación se muestran los métodos de lista disponibles en Clojure.

No Señor. Listas y descripción
1 lista*

Crea una nueva lista que contiene los elementos antepuestos al resto, el último de los cuales se tratará como una secuencia.

2 primero

Esta función devuelve el primer elemento de la lista.

3 enésimo

Esta función devuelve el elemento en la posición 'n-ésima' en la lista.

4 contras

Devuelve una nueva lista en la que se agrega un elemento al principio de la lista.

5 conj

Devuelve una nueva lista en la que la lista está al principio y los elementos que se agregarán al final.

6 descanso

Devuelve los elementos restantes de la lista después del primer elemento.

Setsen Clojure hay un conjunto de valores únicos. Los conjuntos se crean en Clojure con la ayuda del comando set.

Ejemplo

A continuación se muestra un ejemplo de la creación de conjuntos en Clojure.

(ns clojure.examples.example
   (:gen-class))
(defn example []
   (println (set '(1 1 2 2))))
(example)

Salida

El código anterior produce la siguiente salida.

#{1,2}

A continuación se muestran los métodos disponibles en Clojure para conjuntos.

No Señor. Conjuntos y descripción
1 conjunto ordenado

Devuelve un conjunto ordenado de elementos.

2 obtener

Devuelve el elemento en la posición del índice.

3 contiene?

Descubre si el conjunto contiene un determinado elemento o no.

4 conj

Agrega un elemento al conjunto y devuelve el nuevo conjunto de elementos.

5 disj

Se separa un elemento del conjunto.

6 Unión

Devuelve un conjunto que es la unión de los conjuntos de entrada.

7 diferencia

Devuelve un conjunto que es el primer conjunto sin elementos de los conjuntos restantes.

8 intersección

Devuelve un conjunto que es la intersección de los conjuntos de entrada.

9 ¿subconjunto?

¿Es set1 un subconjunto de set2?

10 superconjunto?

¿Es set1 un superconjunto de set2?

UN Vectores una colección de valores indexados por enteros contiguos. Un vector se crea utilizando el método de vector en Clojure.

Ejemplo

A continuación se muestra un ejemplo de cómo crear un vector en Clojure.

(ns clojure.examples.example
   (:require [clojure.set :as set])
   (:gen-class))
(defn example []
   (println (vector 1 2 3)))
(example)

Salida

El código anterior produce la siguiente salida.

[1 2 3]

A continuación se muestran los métodos disponibles en Clojure.

No Señor. Vectores y descripción
1 vector de

Crea un nuevo vector de un solo tipo primitivo 't', donde 't' es uno de: int: long: float: double: byte: short: char o: boolean.

2 enésimo

Esta función devuelve el elemento en la enésima posición del vector.

3 obtener

Devuelve el elemento en la posición del índice en el vector.

4 conj

Agrega un elemento al vector y devuelve el nuevo conjunto de elementos vectoriales.

5 popular

Para una lista o cola, devuelve una nueva lista / cola sin el primer elemento, para un vector, devuelve un nuevo vector sin el último elemento.

6 subvec

Devuelve un sub vector de un índice inicial y final.

UN Mapes una colección que asigna claves a valores. Se proporcionan dos tipos de mapas diferentes: hash y ordenados.HashMaps requieren claves que admitan correctamente hashCode y equals. SortedMaps requieren claves que implementen Comparable, o una instancia de Comparator.

Se puede crear un mapa de dos formas, la primera es mediante el método hash-map.

Creación - HashMaps

Los HashMaps tienen una relación clave-valor típica y se crean utilizando la función hash-map.

(ns clojure.examples.example
   (:gen-class))
(defn example []
   (def demokeys (hash-map "z" "1" "b" "2" "a" "3"))
   (println demokeys))
(example)

Salida

El código anterior produce la siguiente salida.

{z 1, b 2, a 3}

Creación - SortedMaps

SortedMaps tiene la característica única de ordenar sus elementos en función del elemento clave. A continuación se muestra un ejemplo que muestra cómo se puede crear el mapa ordenado usando la función de mapa ordenado.

(ns clojure.examples.example
   (:gen-class))
(defn example []
   (def demokeys (sorted-map "z" "1" "b" "2" "a" "3"))
   (println demokeys))
(example)

El código anterior produce la siguiente salida.

{a 3, b 2, z 1}

En el programa anterior, puede ver claramente que los elementos en los mapas están ordenados según el valor de la clave. A continuación se muestran los métodos disponibles para mapas.

No Señor. Mapas y descripción
1 obtener

Devuelve el valor asignado a clave, no encontrado o nulo si la clave no está presente.

2 contiene?

Vea si el mapa contiene una clave requerida.

3 encontrar

Devuelve la entrada de mapa para la clave.

4 llaves

Devuelve la lista de claves en el mapa.

5 vals

Devuelve la lista de valores en el mapa.

6 dissoc

Disocia una entrada de valor clave del mapa.

7 unir

Fusiona dos entradas de mapas en una sola entrada de mapa.

8 fusionarse con

Devuelve un mapa que consta del resto de los mapas conjugados con el primero.

9 seleccionar-teclas

Devuelve un mapa que contiene solo aquellas entradas en el mapa cuya clave está en claves.

10 cambiar el nombre de las claves

Cambia el nombre de las claves en el HashMap actual a las recién definidas.

11 mapa-invertir

Invierte los mapas para que los valores se conviertan en claves y viceversa.

Namespacesen Clojure se utilizan para diferenciar clases en espacios lógicos separados al igual que en Java. Considere la siguiente declaración.

(:require [clojure.set :as set])

En la declaración anterior, 'clojure.set' es un espacio de nombres que contiene varias clases y métodos que se utilizarán en el programa. Por ejemplo, el espacio de nombres anterior contiene la función llamada map-invert, que se utiliza para invertir un mapa de valores-clave. No podemos usar esta función a menos que le digamos explícitamente a nuestro programa que incluya este espacio de nombres.

Veamos los diferentes métodos disponibles para los espacios de nombres.

No Señor. Métodos y descripción
1 * ns *

Esto se usa para ver su espacio de nombres actual.

2 ns

Esto se usa para crear un nuevo espacio de nombres y asociarlo con el programa en ejecución.

3 alias

Agregue un alias en el espacio de nombres actual a otro espacio de nombres. Los argumentos son dos símbolos: el alias que se utilizará y el nombre simbólico del espacio de nombres de destino.

4 todo-ns

Devuelve una lista de todos los espacios de nombres.

5 find-ns

Busca y devuelve un espacio de nombres en particular.

6 ns-nombre

Devuelve el nombre de un espacio de nombres en particular.

7 ns-alias

Devuelve los alias, que están asociados con cualquier espacio de nombres.

8 ns-map

Devuelve un mapa de todas las asignaciones del espacio de nombres.

9 un-alias

Devuelve un mapa que contiene solo aquellas entradas en el mapa cuya clave está en claves.

Exception handlingSe requiere en cualquier lenguaje de programación para manejar los errores de tiempo de ejecución de modo que se pueda mantener el flujo normal de la aplicación. La excepción generalmente interrumpe el flujo normal de la aplicación, razón por la cual necesitamos usar el manejo de excepciones en nuestra aplicación.

La excepción se clasifica ampliamente en las siguientes categorías:

  • Checked Exception- Las clases que amplían la clase Throwable excepto RuntimeException y Error se conocen como excepciones comprobadas. Por ejemplo, IOException, SQLException, etc. Las excepciones marcadas se comprueban en tiempo de compilación.

Consideremos el siguiente programa que realiza una operación en un archivo llamado Example.txt. Sin embargo, siempre puede haber un caso en el que el archivo Example.txt no exista.

(ns clojure.examples.example
   (:gen-class))

;; This program displays Hello World
(defn Example []
   (def string1 (slurp "Example.txt"))
   (println string1))
(Example)

Si el archivo Example.txt no existe, el programa generará la siguiente excepción.

Caused by: java.io.FileNotFoundException: Example.txt (No such file or
directory)
at java.io.FileInputStream.open0(Native Method)
at java.io.FileInputStream.open(FileInputStream.java:195)
at java.io.FileInputStream.<init>(FileInputStream.java:138)
at clojure.java.io$fn__9185.invoke(io.clj:229) at clojure.java.io$fn__9098$G__9091__9105.invoke(io.clj:69) at clojure.java.io$fn__9197.invoke(io.clj:258)
at clojure.java.io$fn__9098$G__9091__9105.invoke(io.clj:69)

De la excepción anterior, podemos ver claramente que el programa generó una FileNotFoundException.

  • Unchecked Exception- Las clases que amplían RuntimeException se conocen como excepciones no comprobadas. Por ejemplo, ArithmeticException, NullPointerException, ArrayIndexOutOfBoundsException, etc. Las excepciones no marcadas no se comprueban en tiempo de compilación, sino que se comprueban en tiempo de ejecución.

Un caso clásico es la excepción ArrayIndexOutOfBoundsException que ocurre cuando intenta acceder a un índice de una matriz que es mayor que la longitud de la matriz. A continuación se muestra un ejemplo típico de este tipo de error.

(ns clojure.examples.example
   (:gen-class))
(defn Example []
   (try
      (aget (int-array [1 2 3]) 5)
      (catch Exception e (println (str "caught exception: " (.toString e))))
      (finally (println "This is our final block")))
   (println "Let's move on"))
(Example)

Cuando se ejecuta el código anterior, se generará la siguiente excepción.

caught exception: java.lang.ArrayIndexOutOfBoundsException: 5
This is our final block
Let's move on

Error

El error es irrecuperable, por ejemplo, OutOfMemoryError, VirtualMachineError, AssertionError, etc. Estos son errores de los que el programa nunca puede recuperarse y provocarán que el programa se bloquee. Ahora necesitamos algún mecanismo para detectar estas excepciones para que el programa pueda continuar ejecutándose si existen estas excepciones.

El siguiente diagrama muestra cómo se organiza la jerarquía de excepciones en Clojure. Todo se basa en la jerarquía definida en Java.

Captura de excepciones

Al igual que otros lenguajes de programación, Clojure proporciona el bloque normal 'try-catch' para detectar excepciones a medida que ocurren.

A continuación se muestra la sintaxis general del bloque try-catch.

(try
   (//Protected code)
   catch Exception e1)
(//Catch block)

Todo su código que podría generar una excepción se coloca en el Protected code block.

En el catch block, puede escribir código personalizado para manejar su excepción para que la aplicación pueda recuperarse de la excepción.

Veamos nuestro ejemplo anterior que generó una excepción de archivo no encontrado y veamos cómo podemos usar el bloque try catch para detectar la excepción generada por el programa.

(ns clojure.examples.example
   (:gen-class))
(defn Example []
   (try
      (def string1 (slurp "Example.txt"))
      (println string1)
      (catch Exception e (println (str "caught exception: " (.getMessage e))))))
(Example)

El programa anterior produce la siguiente salida.

caught exception: Example.txt (No such file or directory)

Del código anterior, terminamos el código defectuoso en el try block. En el bloque catch, solo estamos detectando nuestra excepción y enviando un mensaje de que se ha producido una excepción. Entonces, ahora tenemos una forma significativa de capturar la excepción, que es generada por el programa.

Múltiples bloques de captura

Uno puede tener múltiples bloques de captura para manejar múltiples tipos de excepciones. Para cada bloque de captura, dependiendo del tipo de excepción generada, escribiría código para manejarlo en consecuencia.

Modifiquemos nuestro código anterior para incluir dos bloques de captura, uno que es específico para nuestra excepción de archivo no encontrado y el otro es para un bloque de excepción general.

(ns clojure.examples.example
   (:gen-class))
(defn Example []
   (try
      (def string1 (slurp "Example.txt"))
      (println string1)
      
      (catch java.io.FileNotFoundException e (println (str "caught file
         exception: " (.getMessage e))))
      
      (catch Exception e (println (str "caught exception: " (.getMessage e)))))
   (println "Let's move on"))
(Example)

El programa anterior produce la siguiente salida.

caught file exception: Example.txt (No such file or directory)
Let's move on

De la salida anterior, podemos ver claramente que nuestra excepción fue detectada por el bloque de captura 'FileNotFoundException' y no por el general.

Finalmente bloquear

El bloque finalmente sigue a un bloque try o un bloque catch. Un bloque de código final siempre se ejecuta, independientemente de la ocurrencia de una excepción.

El uso de un bloque finalmente le permite ejecutar cualquier declaración de tipo limpieza que desee ejecutar, sin importar lo que suceda en el código protegido. A continuación se muestra la sintaxis de este bloque.

(try
   (//Protected code)
   catch Exception e1)
(//Catch block)
(finally
   //Cleanup code)

Modifiquemos el código anterior y agreguemos el bloque de código finalmente. A continuación se muestra el fragmento de código.

(ns clojure.examples.example
   (:gen-class))
(defn Example []
   (try
      (def string1 (slurp "Example.txt"))
      (println string1)
      
      (catch java.io.FileNotFoundException e (println (str "caught file
         exception: " (.getMessage e))))
      
      (catch Exception e (println (str "caught exception: " (.getMessage e))))
      (finally (println "This is our final block")))
   (println "Let's move on"))
(Example)

El programa anterior produce la siguiente salida.

caught file exception: Example.txt (No such file or directory)
This is our final block
Let's move on

En el programa anterior, puede ver que el bloque final también se implementa después de que el bloque catch detecta la excepción requerida.

Dado que Clojure deriva su manejo de excepciones de Java, similar a Java, los siguientes métodos están disponibles en Clojure para administrar las excepciones.

  • public String getMessage()- Devuelve un mensaje detallado sobre la excepción que se ha producido. Este mensaje se inicializa en el constructor Throwable.

  • public Throwable getCause() - Devuelve la causa de la excepción representada por un objeto Throwable.

  • public String toString() - Devuelve el nombre de la clase concatenada con el resultado de getMessage ().

  • public void printStackTrace() - Imprime el resultado de toString () junto con el seguimiento de la pila en System.err, el flujo de salida del error.

  • public StackTraceElement [] getStackTrace()- Devuelve una matriz que contiene cada elemento en el seguimiento de la pila. El elemento en el índice 0 representa la parte superior de la pila de llamadas y el último elemento de la matriz representa el método en la parte inferior de la pila de llamadas.

  • public Throwable fillInStackTrace() - Rellena el seguimiento de la pila de este objeto Throwable con el seguimiento de la pila actual, agregando a cualquier información anterior en el seguimiento de la pila.

A continuación se muestra el código de ejemplo que utiliza algunos de los métodos enumerados anteriormente.

(ns clojure.examples.example
   (:gen-class))
(defn Example []
   (try
      (def string1 (slurp "Example.txt"))
      (println string1)
      
      (catch java.io.FileNotFoundException e (println (str "caught file
         exception: " (.toString e))))
      
      (catch Exception e (println (str "caught exception: " (.toString e))))
   (finally (println "This is our final block")))
   (println "Let's move on"))
(Example)

El programa anterior produce la siguiente salida.

caught file exception: java.io.FileNotFoundException: Example.txt (No such file
or directory)
This is our final block
Let's move on

Sequences se crean con la ayuda de ‘seq’mando. A continuación se muestra un ejemplo simple de creación de una secuencia.

(ns clojure.examples.example
   (:gen-class))

;; This program displays Hello World
(defn Example []
   (println (seq [1 2 3])))
(Example)

El programa anterior produce la siguiente salida.

(1 2 3)

A continuación se muestran los diversos métodos disponibles para las secuencias.

No Señor. Métodos y descripción
1 contras

Devuelve una nueva secuencia donde 'x' es el primer elemento y 'seq' es el resto.

2 conj

Devuelve una nueva secuencia donde 'x' es el elemento que se agrega al final de la secuencia.

3 concat

Esto se usa para combinar dos secuencias.

4 distinto

Se usa solo para garantizar que se agreguen elementos distintos a la secuencia.

5 contrarrestar

Invierte los elementos de la secuencia.

6 primero

Devuelve el primer elemento de la secuencia.

7 último

Devuelve el último elemento de la secuencia.

8 descanso

Devuelve la secuencia completa excepto el primer elemento.

9 ordenar

Devuelve una secuencia ordenada de elementos.

10 soltar

Elimina elementos de una secuencia en función del número de elementos que deben eliminarse.

11 tomar el último

Toma la última lista de elementos de la secuencia.

12 tomar

Toma la primera lista de elementos de la secuencia.

13 dividido en

Divide la secuencia de elementos en dos partes. Se especifica una ubicación en la que debe ocurrir la división.

UN regular expressiones un patrón que se utiliza para buscar subcadenas en el texto. Las expresiones regulares se usan en una variedad de lenguajes de programación y se usan mucho en lenguajes de programación de tipo LISP.

A continuación se muestra un ejemplo de una expresión regular.

//d+

La expresión regular anterior se usa para encontrar una ocurrencia más de un dígito en una cadena. Los caracteres // se utilizan para garantizar que los caracteres 'd' y '+' se utilicen para representar una expresión regular.

En general, las expresiones regulares funcionan con el siguiente conjunto de reglas.

  • Hay dos caracteres posicionales especiales que se utilizan para indicar el principio y el final de una línea: el símbolo de intercalación (∧) y el signo de dólar ($):

  • Las expresiones regulares también pueden incluir cuantificadores. El signo más (+) representa una o más veces, aplicado al elemento anterior de la expresión. El asterisco (*) se utiliza para representar cero o más ocurrencias. El signo de interrogación (?) Denota cero o una vez.

  • El metacarácter {y} se utiliza para coincidir con un número específico de instancias del carácter anterior.

  • En una expresión regular, el símbolo de punto (.) Puede representar cualquier carácter. Esto se describe como el carácter comodín.

  • Una expresión regular puede incluir clases de caracteres. Un conjunto de caracteres se puede dar como una secuencia simple de caracteres encerrados en los metacaracteres [y] como en [aeiou]. Para rangos de letras o números, puede usar un separador de guiones como en [a – z] o [a – mA – M]. El complemento de una clase de caracteres se indica con un signo de intercalación inicial entre corchetes como en [∧a – z] y representa todos los caracteres distintos de los especificados.

Los siguientes métodos están disponibles para expresiones regulares.

No Señor. Métodos y descripción
1 re-patrón

Devuelve una instancia de java.util.regex.Pattern. Esto se utiliza luego en otros métodos para la coincidencia de patrones.

2 reencontrar

Devuelve la siguiente coincidencia de expresiones regulares, si la hay, de la cadena al patrón, utilizando java.util.regex.Matcher.find ()

3 reemplazar

La función de reemplazo se usa para reemplazar una subcadena en una cadena con un nuevo valor de cadena. La búsqueda de la subcadena se realiza con el uso de un patrón.

4 reemplazar primero

La función de reemplazo se usa para reemplazar una subcadena en una cadena con un nuevo valor de cadena, pero solo para la primera aparición de la subcadena. La búsqueda de la subcadena se realiza con el uso de un patrón.

Predicatesson funciones que evalúan una condición y proporcionan un valor de verdadero o falso. Hemos visto funciones de predicado en los ejemplos del capítulo sobre números. Hemos visto funciones como 'incluso?' que se usa para probar si un número es par o no, o "neg"? que se usa para probar si un número es mayor que cero o no. Todas estas funciones devuelven un valor verdadero o falso.

A continuación se muestra un ejemplo de predicados en Clojure.

(ns clojure.examples.example
   (:gen-class))

;; This program displays Hello World
(defn Example []
   (def x (even? 0))
   (println x)
   
   (def x (neg? 2))
   (println x)
   
   (def x (odd? 3))
   (println x)
   
   (def x (pos? 3))
   (println x))
(Example)

El programa anterior produce la siguiente salida.

true
false
true
true

Además de las funciones de predicado normales, Clojure proporciona más funciones para los predicados. Los siguientes métodos están disponibles para predicados.

No Señor. Métodos y descripción
1 cada pred

Toma un conjunto de predicados y devuelve una función 'f' que devuelve verdadero si todos los predicados que lo componen devuelven un valor lógico verdadero frente a todos sus argumentos; de lo contrario, devuelve falso.

2 ¿cada?

Devuelve verdadero si el predicado es verdadero para cada valor, de lo contrario es falso.

3 algunos

Devuelve el primer valor lógico verdadero para cualquier valor de predicado de x en la colección de valores.

4 ¿no cualquiera?

Devuelve falso si alguno de los predicados de los valores de una colección es lógicamente verdadero; de lo contrario, verdadero.

Destructuring es una funcionalidad dentro de Clojure, que permite extraer valores de una estructura de datos, como un vector, y vincularlos a símbolos sin tener que atravesar explícitamente la estructura de datos.

Veamos un ejemplo de lo que significa exactamente Desestructurar y cómo ocurre.

Ejemplo

(ns clojure.examples.example
   (:gen-class))
(defn Example []
   (def my-vector [1 2 3 4])
   (let [[a b c d] my-vector]
   (println a b c d)))
(Example)

El programa anterior produce la siguiente salida.

Salida

1 2 3 4

En el ejemplo anterior, se deben tener en cuenta las siguientes cosas:

  • Estamos definiendo un vector de números enteros como 1, 2, 3 y 4.

  • Entonces estamos usando el ‘let’ declaración para asignar 4 variables (a, b, c y d) a la variable my-vector directamente.

  • Si ejecutamos el ‘println’ declaración sobre las cuatro variables, podemos ver que ya se han asignado a los valores en el vector respectivamente.

Entonces clojure ha desestructurado la variable my-vector que tiene cuatro valores cuando se asignó usando la declaración 'let'. Los cuatro valores deconstruidos se asignaron luego a los cuatro parámetros en consecuencia.

Si hay un exceso de variables que no tienen un valor correspondiente al que pueden asignarse, entonces se les asignará el valor de cero. El siguiente ejemplo aclara este punto.

Ejemplo

(ns clojure.examples.hello
   (:gen-class))
(defn Example []
   (def my-vector [1 2 3 4])
   (let [[a b c d e] my-vector]
   (println a b c d e)))
(Example)

El programa anterior produce la siguiente salida. Puede ver en la salida que, dado que la última variable 'e' no tiene un valor correspondiente en el vector, cuenta como cero.

Salida

1 2 3 4 nil

el resto

La variable 'el resto' se utiliza para almacenar los valores restantes, que no se pueden asignar a ninguna variable.

Un ejemplo de cómo se utiliza se muestra en el siguiente programa.

Ejemplo

(ns clojure.examples.example
   (:gen-class))
(defn Example []
   (def my-vector [1 2 3 4])
   (let [[a b & the-rest] my-vector]
   (println a b the-rest)))
(Example)

El programa anterior produce la siguiente salida. En el resultado, puede ver claramente que los valores de 3 y 4 no se pueden asignar a ninguna variable, por lo que se asignan a la variable 'el resto'.

Salida

1 2 (3 4)

Desestructuración de mapas

Al igual que los vectores, los mapas también se pueden desestructurar. A continuación se muestra un ejemplo de cómo se puede lograr esto.

Ejemplo

(ns clojure.examples.example
   (:gen-class))
(defn Example []
   (def my-map {"a" 1 "b" 2})
   (let [{a "a" b "b"} my-map]
   (println a b)))
(Example)

El programa anterior produce la siguiente salida. Desde el programa se puede ver claramente que los valores del mapa de “a” y “b” están asignados a las variables de ay b.

Salida

1 2

De manera similar, en el caso de los vectores, si no hay un valor correspondiente en el mapa cuando ocurre la desestructuración, entonces a la variable se le asignará un valor de cero.

A continuación se muestra un ejemplo.

Ejemplo

(ns clojure.examples.example
   (:gen-class))
(defn Example []
   (def my-map {"a" 1 "b" 2})
   (let [{a "a" b "b" c "c"} my-map]
   (println a b c)))
(Example)

El programa anterior produce la siguiente salida.

Salida

1 2 nil

Dado que el marco de trabajo de Clojure se deriva de las clases de Java, se pueden usar las clases de fecha y hora disponibles en Java en Clojure. losclass date representa un instante específico en el tiempo, con precisión de milisegundos.

A continuación se muestran los métodos disponibles para la clase de fecha y hora.

java.util.Date

Esto se usa para crear el objeto de fecha en Clojure.

Sintaxis

A continuación se muestra la sintaxis.

java.util.Date.

Parameters - Ninguno.

Return Value - Asigna un objeto Date y lo inicializa para que represente la hora en la que fue asignado, medido al milisegundo más cercano.

Ejemplo

Un ejemplo de cómo se utiliza se muestra en el siguiente programa.

(ns example)
(defn Example []
   (def date (.toString (java.util.Date.)))
   (println date))
(Example)

Salida

El programa anterior produce la siguiente salida. Esto dependerá de la fecha y hora actuales del sistema en el que se ejecuta el programa.

Tue Mar 01 06:11:17 UTC 2016

java.text.SimpleDateFormat

Se utiliza para formatear la salida de la fecha.

Sintaxis

A continuación se muestra la sintaxis.

(java.text.SimpleDateFormat. format dt)

Parameters- 'formato' es el formato que se utilizará al formatear la fecha. 'dt' es la fecha que debe formatearse.

Return Value - Una salida de fecha formateada.

Ejemplo

Un ejemplo de cómo se utiliza se muestra en el siguiente programa.

(ns example)
(defn Example []
   (def date (.format (java.text.SimpleDateFormat. "MM/dd/yyyy") (new java.util.Date)))
   (println date))
(Example)

Salida

El programa anterior produce la siguiente salida. Esto dependerá de la fecha y hora actuales del sistema en el que se ejecuta el programa.

03/01/2016

consigue tiempo

Devuelve el número de milisegundos desde el 1 de enero de 1970 a las 00:00:00 GMT representado por este objeto Date.

Sintaxis

A continuación se muestra la sintaxis.

(.getTime)

Parameters - Ninguno.

Return Value - El número de milisegundos desde el 1 de enero de 1970 a las 00:00:00 GMT representado por esta fecha.

Ejemplo

Un ejemplo de cómo se utiliza se muestra en el siguiente programa.

(ns example)
(import java.util.Date)
(defn Example []
   (def date (.getTime (java.util.Date.)))
   (println date))
(Example)

Salida

El programa anterior produce la siguiente salida. Esto dependerá de la fecha y hora actuales del sistema en el que se ejecuta el programa.

1456812778160

Atomsson un tipo de datos en Clojure que proporcionan una forma de administrar el estado compartido, síncrono e independiente. Un átomo es como cualquier tipo de referencia en cualquier otro lenguaje de programación. El uso principal de un átomo es mantener las estructuras de datos inmutables de Clojure. El valor de un átomo se cambia con elswap! method.

Internamente, intercambiar! lee el valor actual, le aplica la función e intenta compararlo y establecerlo. Dado que otro subproceso puede haber cambiado el valor en el tiempo intermedio, es posible que tenga que volver a intentarlo y lo hace en un bucle giratorio. El efecto neto es que el valor siempre será el resultado de la aplicación de la función proporcionada a un valor actual, atómicamente.

Ejemplo

Los átomos se crean con la ayuda del método del átomo. Un ejemplo del mismo se muestra en el siguiente programa.

(ns clojure.examples.example
   (:gen-class))
(defn example []
   (def myatom (atom 1))
   (println @myatom))
(example)

Salida

El programa anterior produce el siguiente resultado.

1

Se accede al valor del átomo mediante el símbolo @. Clojure tiene algunas operaciones que se pueden realizar en átomos. Las siguientes son las operaciones.

No Señor. Operaciones y descripción
1 ¡Reiniciar!

Establece el valor del átomo en un nuevo valor sin tener en cuenta el valor actual.

2 comparar y configurar!

Atómicamente establece el valor del átomo en el nuevo valor si y solo si el valor actual del átomo es idéntico al valor anterior que tenía el átomo. Devuelve verdadero si ocurre un conjunto, de lo contrario devuelve falso.

3 ¡intercambiar!

Atómicamente intercambia el valor del átomo con uno nuevo basado en una función particular.

En Clojure, metadatase utiliza para anotar los datos en una colección o para los datos almacenados en un símbolo. Esto se usa normalmente para anotar datos sobre tipos en el compilador subyacente, pero también se puede usar para desarrolladores. Los metadatos no se consideran parte del valor del objeto. Al mismo tiempo, los metadatos son inmutables.

Las siguientes operaciones son posibles en Clojure con respecto a los metadatos.

No Señor. Operaciones y descripción
1 meta-con

Esta función se utiliza para definir un mapa de metadatos para cualquier objeto.

2 meta

Esta función se usa para ver si algún metadato está asociado con un objeto.

3 variar-meta

Devuelve un objeto del mismo tipo y valor que el objeto original, pero con metadatos combinados.

StructMapsse utilizan para crear estructuras en Clojure. Por ejemplo, si desea crear una estructura que consta de un nombre de empleado y un ID de empleado, puede hacerlo con StructMaps.

Las siguientes operaciones son posibles en Clojure con respecto a StructMaps.

No Señor. Operaciones y descripción
1 defstruct

Esta función se utiliza para definir la estructura que se requiere.

2 estructura

Esta función se utiliza para definir un objeto de estructura del tipo, que se crea mediante la operación defstruct.

3 estructura-mapa

Esta función se utiliza para asignar específicamente valores a valores clave definiendo explícitamente qué valores se asignan a qué claves en la estructura.

4 Acceder a campos individuales

Se puede acceder a los campos individuales de la estructura accediendo a las claves junto con el objeto de la estructura.

5 Naturaleza inmutable

Por defecto, las estructuras también son inmutables, por lo que si intentamos cambiar el valor de una clave en particular, no cambiará.

6 Agregar una nueva clave a la estructura

Dado que las estructuras son inmutables, la única forma en que se puede agregar otra clave a la estructura es mediante la creación de una nueva estructura. En el siguiente programa se muestra un ejemplo de cómo se puede lograr esto.

Como se señaló muchas veces, Clojure es un lenguaje de programación en el que muchos de los tipos de datos son inmutables, lo que significa que la única forma en que uno puede cambiar el valor de una variable es crear una nueva variable y asignarle el nuevo valor. Sin embargo, Clojure proporciona algunos elementos que pueden crear un estado mutable. Hemos visto que esto se puede lograr con el tipo de datos atom. La otra forma en que esto se puede lograr es a través de agentes.

AgentsProporcionar cambios independientes y asincrónicos de ubicaciones individuales. Los agentes están vinculados a una única ubicación de almacenamiento durante toda su vida y solo permiten que se produzca la mutación de esa ubicación (a un nuevo estado) como resultado de una acción. Las acciones son funciones (con, opcionalmente, argumentos adicionales) que se aplican de forma asincrónica al estado de un Agente y cuyo valor de retorno se convierte en el nuevo estado del Agente.

Las siguientes operaciones son posibles en Clojure con respecto a los agentes.

No Señor. Operaciones y descripción
1 agente

Un agente se crea mediante el comando de agente.

2 enviar

Esta función se utiliza para enviar un valor al agente.

3 agentes de cierre

Esta función se utiliza para apagar cualquier agente en ejecución.

4 enviar

Hay casos en los que a un agente se le asigna una función que es de naturaleza bloqueante.

5 esperar

Dado que hay una demora cuando se actualiza un valor de un agente, Clojure proporcionó una función de 'espera' que se usa para especificar el tiempo en milisegundos para esperar a que se actualice el agente.

6 esperar

Bloquea el hilo actual (¡indefinidamente!) Hasta que todas las acciones despachadas hasta ahora, desde este hilo o agente, al agente (s) hayan ocurrido. Bloqueará a los agentes fallidos.

7 agente-error

Devuelve la excepción lanzada durante una acción asincrónica del agente, si el agente falla. Devuelve nil si el agente no falla.

Watchersson funciones agregadas a tipos de variables como átomos y variables de referencia que se invocan cuando cambia un valor del tipo de variable. Por ejemplo, si el programa de llamada cambia el valor de una variable de átomo, y si una función de observador está asociada a la variable de átomo, la función se invocará tan pronto como se cambie el valor del átomo.

Las siguientes funciones están disponibles en Clojure para Watchers.

añadir reloj

Agrega una función de vigilancia a una referencia de agente / átomo / var / ref. El reloj‘fn’debe ser un 'fn' de 4 argumentos: una clave, la referencia, su estado anterior, su estado nuevo. Siempre que se haya cambiado el estado de la referencia, se llamarán sus funciones a cualquier reloj registrado.

Sintaxis

A continuación se muestra la sintaxis.

(add-watch variable :watcher
   (fn [key variable-type old-state new-state]))

Parameters- 'variable' es el nombre del átomo o variable de referencia. 'variable-type' es el tipo de variable, ya sea átomo o variable de referencia. 'old-state & new-state' son parámetros que mantendrán automáticamente el valor antiguo y nuevo de la variable. La 'clave' debe ser única por referencia y se puede usar para quitar el reloj con remove-watch.

Return Value - Ninguno.

Ejemplo

Un ejemplo de cómo se utiliza se muestra en el siguiente programa.

(ns clojure.examples.example
   (:gen-class))
(defn Example []
   (def x (atom 0))
   (add-watch x :watcher
      (fn [key atom old-state new-state]
      (println "The value of the atom has been changed")
      (println "old-state" old-state)
      (println "new-state" new-state)))
(reset! x 2))
(Example)

Salida

El programa anterior produce la siguiente salida.

The value of the atom has been changed
old-state 0
new-state 2

quitar reloj

Elimina un reloj que se ha adjuntado a una variable de referencia.

Sintaxis

A continuación se muestra la sintaxis.

(remove-watch variable watchname)

Parameters- 'variable' es el nombre del átomo o variable de referencia. 'watchname' es el nombre que se le da al reloj cuando se define la función de reloj.

Return Value - Ninguno.

Ejemplo

Un ejemplo de cómo se utiliza se muestra en el siguiente programa.

(ns clojure.examples.example
   (:gen-class))
(defn Example []
   (def x (atom 0))
   (add-watch x :watcher
      (fn [key atom old-state new-state]
         (println "The value of the atom has been changed")
         (println "old-state" old-state)
         (println "new-state" new-state)))
   (reset! x 2)
   (remove-watch x :watcher)
(reset! x 4))
(Example)

Salida

El programa anterior produce la siguiente salida.

The value of the atom has been changed
old-state 0
new-state 2

Puede ver claramente en el programa anterior que el segundo comando de reinicio no activa al observador ya que fue eliminado de la lista de observadores.

En cualquier idioma, Macrosse utilizan para generar código en línea. Clojure no es una excepción y proporciona facilidades de macro simples para los desarrolladores. Las macros se utilizan para escribir rutinas de generación de código, que proporcionan al desarrollador una forma poderosa de adaptar el lenguaje a las necesidades del desarrollador.

A continuación se muestran los métodos disponibles para macros.

defmacro

Esta función se utiliza para definir su macro. La macro tendrá un nombre de macro, una lista de parámetros y el cuerpo de la macro.

Sintaxis

A continuación se muestra la sintaxis.

(defmacro name [params*] body)

Parameters- 'nombre' es el nombre de la macro. 'params' son los parámetros asignados a la macro. 'cuerpo' es el cuerpo de la macro.

Return Value - Ninguno.

Ejemplo

Un ejemplo de cómo se utiliza se muestra en el siguiente programa.

(ns clojure.examples.example
   (:gen-class))
(defn Example []
   (defmacro Simple []
      (println "Hello"))
   (macroexpand '(Simple)))
(Example)

Salida

El programa anterior produce la siguiente salida.

Hello

En el programa anterior puede ver que la macro 'Simple' se expande en línea a 'println' "Hola". Las macros son similares a las funciones, con la única diferencia de que los argumentos de un formulario se evalúan en el caso de las macros.

macro-expandir

Esto se usa para expandir una macro y colocar el código en línea en el programa.

Sintaxis

A continuación se muestra la sintaxis.

(macroexpand macroname)

Parameters - 'macroname' es el nombre de la macro que debe expandirse.

Return Value - La macro expandida.

Ejemplo

Un ejemplo de cómo se utiliza se muestra en el siguiente programa.

(ns clojure.examples.example
   (:gen-class))
(defn Example []
   (defmacro Simple []
      (println "Hello"))
   (macroexpand '(Simple)))
(Example)

Salida

El programa anterior produce la siguiente salida.

Hello

Macro con argumentos

Las macros también se pueden utilizar para incorporar argumentos. La macro puede aceptar cualquier número de argumentos. El siguiente ejemplo muestra cómo se pueden usar los argumentos.

Ejemplo

(ns clojure.examples.example
   (:gen-class))
(defn Example []
   (defmacro Simple [arg]
      (list 2 arg))
   (println (macroexpand '(Simple 2))))
(Example)

El ejemplo anterior coloca un argumento en la macro Simple y luego usa el argumento para agregar un valor de argumento a una lista.

Salida

El programa anterior produce la siguiente salida.

(2 2)

Reference valuesson otra forma en que Clojure puede trabajar con la demanda de tener variables mutables. Clojure proporciona tipos de datos mutables como átomos, agentes y tipos de referencia.

A continuación se muestran las operaciones disponibles para valores de referencia.

No Señor. Operaciones y descripción
1 árbitro

Se utiliza para crear un valor de referencia. Al crear un valor de referencia, existe la opción de proporcionar una función de validación, que validará el valor creado.

2 ref-set

Esta función se utiliza para establecer el valor de una referencia a un nuevo valor independientemente del valor anterior.

3 alterar

Esta función se utiliza para alterar el valor de un tipo de referencia pero de manera segura. Esto se ejecuta en un hilo, al que no puede acceder ningún otro proceso.

4 dosync

Ejecuta la expresión (en un do implícito) en una transacción que abarca la expresión y cualquier llamada anidada.

5 conmutar

Commute también se usa para cambiar el valor de un tipo de referencia al igual que alter y ref-set.

Para utilizar la funcionalidad de la base de datos, asegúrese de descargar primero el jdbc files de la siguiente URL: https://codeload.github.com/clojure/java.jdbc/zip/master

Encontrará un archivo zip que tiene los controladores necesarios para que Clojure tenga la capacidad de conectarse a bases de datos. Una vez que se extrae el archivo zip, asegúrese de agregar la ubicación descomprimida a su classpath.

El archivo principal para la conectividad de la base de datos es un archivo llamado jdbc.clj en la ubicación clojure / java.

El conector clojure jdbc admite una amplia variedad de bases de datos, algunas de las cuales son las siguientes.

  • H2Database
  • Oracle
  • Microsoft SQL Server
  • MySQL
  • PostgreSQL

En nuestro ejemplo, usaremos MySQL DB como ejemplo.

Las siguientes operaciones son posibles en Clojure con respecto a las bases de datos.

Conexión de base de datos

Antes de conectarse a una base de datos MySQL, asegúrese de lo siguiente:

  • Ha creado una base de datos TESTDB.

  • Ha creado una tabla EMPLOYEE en TESTDB.

  • Esta tabla tiene campos FIRST_NAME, LAST_NAME, EDAD, SEXO e INGRESOS.

  • El ID de usuario "testuser" y la contraseña "test123" están configurados para acceder a TESTDB.

  • Asegúrese de haber descargado el 'archivo jar mysql' y agregado el archivo a su classpath.

  • Ha seguido el tutorial de MySQL para comprender los conceptos básicos de MySQL .

Sintaxis

A continuación se muestra la sintaxis para crear una conexión en Clojure.

(def connection_name {
   :subprotocol “protocol_name”
   :subname “Location of mysql DB”
   :user “username” :password “password” })

Parameters- 'nombre_conexión' es el nombre que se le dará a la conexión. 'subprotocol' es el protocolo que se utilizará para la conexión. Por defecto usaremos el protocolo mysql. 'subname' es la URL para conectarse a la base de datos mysql junto con el nombre de la base de datos. 'usuario' es el nombre de usuario utilizado para conectarse a la base de datos. 'contraseña' es la contraseña que se utilizará para conectarse a la base de datos.

Return Value - Esto proporcionará una cadena de conexión, que se puede usar en operaciones subsiguientes de mysql.

El siguiente ejemplo muestra cómo conectarse a las tablas en el esquema de información y recuperar todos los datos de la tabla.

Ejemplo

(ns test.core
   (:require [clojure.java.jdbc :as sql]))
(defn -main []
   (def mysql-db {
      :subprotocol "mysql"
      :subname "//127.0.0.1:3306/information_schema"
      :user "root"
      :password "shakinstev"})
   (println (sql/query mysql-db
      ["select table_name from tables"]
      :row-fn :table_name)))

Consulta de datos

Consultar datos en cualquier base de datos significa obtener información útil de la base de datos. Una vez que se establece una conexión a la base de datos, está listo para realizar una consulta en esta base de datos. A continuación se muestra la sintaxis mediante la cual se pueden consultar los datos utilizando Clojure.

Sintaxis

clojure.java.jdbc/query dbconn
["query"]
   :row-fn :sequence

Parameters- 'dbconn' es el nombre de la conexión utilizada para conectarse a la base de datos. 'consulta' es la cadena de consulta utilizada para obtener datos de la base de datos. ': secuencia' es por defecto todas las filas de datos extraídas de la base de datos y se devuelve como una secuencia. A continuación, se pueden realizar las operaciones necesarias en la secuencia para ver qué datos se han obtenido.

Return Value - Esto devolverá una secuencia, que tendrá las filas de datos de la operación de consulta.

El siguiente ejemplo muestra cómo conectarse a la tabla de empleados y obtener la columna first_name de las filas de la tabla.

Ejemplo

(ns test.core
   (:require [clojure.java.jdbc :as sql]))
(defn -main []
   (def mysql-db {
      :subprotocol "mysql"
      :subname "//127.0.0.1:3306/testdb"
      :user "root"
      :password "shakinstev"})
   (println (sql/query mysql-db
      ["select first_name from employee"]
      :row-fn :first_name)))

En el código anterior, podemos ver que

  • La consulta de "seleccionar el primer nombre del empleado" se pasa como la cadena de consulta.

  • : First_name es la secuencia, que se devuelve como resultado de la operación de búsqueda.

Si asumimos que solo hay una fila en nuestra base de datos que contiene un valor de nombre de pila de John, lo siguiente será el resultado del programa anterior.

(John)

Insertar datos

Es necesario cuando desea crear sus registros en una tabla de base de datos. A continuación se muestra la sintaxis mediante la cual se pueden insertar datos usando Clojure. Esto se hace usando el‘insert!’ función.

Sintaxis

clojure.java.jdbc/insert!
   :table_name {:column_namen columnvalue}

Parameters- ': table_name' es el nombre de la tabla en la que se debe realizar la inserción. '{: column_namen columnvalue}' es un mapa de todos los nombres y valores de las columnas, que deben agregarse como una fila en la tabla.

Return Value - Esto devolverá nil si la inserción se realiza correctamente.

El siguiente ejemplo muestra cómo insertar un registro en la tabla de empleados en la base de datos testdb.

Ejemplo

(ns test.core
   (:require [clojure.java.jdbc :as sql]))
(defn -main []
   (def mysql-db {
      :subprotocol "mysql"
      :subname "//127.0.0.1:3306/testdb"
      :user "root"
      :password "shakinstev"})
   (sql/insert! mysql-db
      :employee {:first_name "John" :last_name "Mark" :sex "M" :age 30 :income 30}))

Si ahora verifica su base de datos MySQL y la tabla de empleados, verá que la fila anterior se insertará correctamente en la tabla.

Eliminar datos

Las filas se pueden eliminar de una tabla usando el ‘delete!’función. A continuación se muestra la sintaxis sobre cómo se puede realizar esta operación.

Sintaxis

clojure.java.jdbc/delete!
   :table_name [condition]

Parameters- ': table_name' es el nombre de la tabla en la que se debe realizar la inserción. 'condición' es la condición que se utiliza para determinar qué fila debe eliminarse de la tabla.

Return Value - Esto devolverá el número de filas eliminadas.

El siguiente ejemplo muestra cómo eliminar un registro de la tabla de empleados en la base de datos testdb. El ejemplo elimina una fila de la tabla según la condición de que la edad sea igual a 30.

Ejemplo

(ns test.core
   (:require [clojure.java.jdbc :as sql]))
(defn -main []
   (def mysql-db {
      :subprotocol "mysql"
      :subname "//127.0.0.1:3306/testdb"
      :user "root"
      :password "shakinstev"})
   (println (sql/delete! mysql-db
      :employee ["age = ? " 30])))

Si tenía un registro que tenía una fila con una edad igual al valor de 30, esa fila se eliminará.

Actualización de datos

Las filas se pueden actualizar desde una tabla usando el ‘update!’función. A continuación se muestra la sintaxis sobre cómo se puede realizar esta operación.

Sintaxis

clojure.java.jdbc/update!
   :table_name
{setcondition}
[condition]

Parameters- ': table_name' es el nombre de la tabla en la que se debe realizar la inserción. 'setcondition' es la columna que debe actualizarse como se menciona en términos de un mapa. 'condición' es la condición que se utiliza para determinar qué fila debe eliminarse de la tabla.

Return Value - Esto devolverá el número de filas actualizadas.

El siguiente ejemplo muestra cómo eliminar un registro de la tabla de empleados en la base de datos testdb. El ejemplo actualiza una fila de la tabla según la condición de que la edad sea igual a 30 y actualiza el valor de los ingresos a 40.

(ns test.core
   (:require [clojure.java.jdbc :as sql]))
(defn -main []
   (def mysql-db {
      :subprotocol "mysql"
      :subname "//127.0.0.1:3306/testdb"
      :user "root"
      :password "shakinstev"})
   (println (sql/update! mysql-db
      :employee
      {:income 40}
      ["age = ? " 30])))

Si tenía un registro que tenía una fila con una edad igual al valor de 30, esa fila se actualizará y el valor de los ingresos se establecerá en 40.

Actas

Las transacciones son mecanismos que garantizan la coherencia de los datos. Las transacciones tienen las siguientes cuatro propiedades:

  • Atomicity - O se completa una transacción o no ocurre nada.

  • Consistency - Una transacción debe comenzar en un estado consistente y dejar el sistema en un estado consistente.

  • Isolation - Los resultados intermedios de una transacción no son visibles fuera de la transacción actual.

  • Durability - Una vez que se comprometió una transacción, los efectos son persistentes, incluso después de una falla del sistema.

Ejemplo

El siguiente ejemplo muestra cómo implementar transacciones en Clojure. Cualquier operación que deba realizarse en una transacción debe integrarse en el‘with-dbtransaction’ cláusula.

(ns test.core
   (:require [clojure.java.jdbc :as sql]))
(defn -main []
   (def mysql-db {
      :subprotocol "mysql"
      :subname "//127.0.0.1:3306/testdb"
      :user "root"
      :password "shakinstev"})
   (sql/with-db-transaction [t-con mysql-db]
      (sql/update! t-con
         :employee
         {:income 40}
         ["age = ? " 30])))

Como ya sabemos, el código de Clojure se ejecuta en el entorno virtual de Java al final. Por lo tanto, tiene sentido que Clojure sea capaz de utilizar todas las funcionalidades de Java. En este capítulo, analicemos la correlación entre Clojure y Java.

Llamar a métodos Java

Los métodos de Java se pueden llamar utilizando la notación de puntos. Un ejemplo son las cuerdas. Dado que todas las cadenas en Clojure son de todos modos cadenas de Java, puede llamar a métodos Java normales en cadenas.

Un ejemplo de cómo se hace esto se muestra en el siguiente programa.

Ejemplo

(ns Project
   (:gen-class))
(defn Example []
   (println (.toUpperCase "Hello World")))
(Example)

El programa anterior produce la siguiente salida. Puede ver en el código que si simplemente llama a la notación de puntos para cualquier método de cadena, también funcionará en Clojure.

Salida

HELLO WORLD

Llamar a métodos Java con parámetros

También puede llamar a métodos Java con parámetros. Un ejemplo de cómo se hace esto se muestra en el siguiente programa.

Ejemplo

(ns Project
   (:gen-class))
(defn Example []
   (println (.indexOf "Hello World","e")))
(Example)

El programa anterior produce la siguiente salida. Puede ver en el código anterior que estamos pasando el parámetro "e" al método indexOf. El programa anterior produce la siguiente salida.

Salida

1

Crear objetos Java

Los objetos se pueden crear en Clojure usando la palabra clave 'nueva' similar a lo que se hace en Java.

Un ejemplo de cómo se hace esto se muestra en el siguiente programa.

Ejemplo

(ns Project
   (:gen-class))
(defn Example []
   (def str1 (new String "Hello"))
   (println str1))
(Example)

El programa anterior produce la siguiente salida. Puede ver en el código anterior, que podemos usar la palabra clave 'nuevo' para crear un nuevo objeto a partir de la clase String existente de Java. Podemos pasar el valor mientras creamos el objeto, tal como lo hacemos en Java. El programa anterior produce la siguiente salida.

Salida

Hello

A continuación se muestra otro ejemplo que muestra cómo podemos crear un objeto de la clase Integer y usarlos en los comandos normales de Clojure.

Ejemplo

(ns Project
   (:gen-class))
(defn Example []
   (def my-int(new Integer 1))
   (println (+ 2 my-int)))
(Example)

El programa anterior produce la siguiente salida.

Salida

3

Importar comando

También podemos usar el comando de importación para incluir bibliotecas de Java en el espacio de nombres para que se pueda acceder fácilmente a las clases y métodos.

El siguiente ejemplo muestra cómo podemos usar el comando de importación. En el ejemplo, estamos usando el comando de importación para importar las clases deljava.util.stackbiblioteca. Entonces podemos usar el método push y pop de la clase de pila tal como están.

Ejemplo

(ns Project
   (:gen-class))
(import java.util.Stack)
(defn Example []
   (let [stack (Stack.)]
   (.push stack "First Element")
   (.push stack "Second Element")
   (println (first stack))))
(Example)

El programa anterior produce la siguiente salida.

Salida

First Element

Ejecución de código mediante el comando Java

El código de Clojure se puede ejecutar usando el comando de Java. A continuación se muestra la sintaxis de cómo se puede hacer esto.

java -jar clojure-1.2.0.jar -i main.clj

Debe mencionar el archivo jar de Clojure, para que todas las clases basadas en Clojure se carguen en la JVM. El archivo 'main.clj' es el archivo de código Clojure que debe ejecutarse.

Funciones integradas de Java

Clojure puede usar muchas de las funciones integradas de Java. Algunos de ellos son ...

Math PI function- Clojure puede usar el método Math con el valor de PI. A continuación se muestra un código de ejemplo.

Ejemplo

(ns Project
   (:gen-class))
(defn Example []
   (println (. Math PI)))
(Example)

El código anterior produce la siguiente salida.

Salida

3.141592653589793

System Properties- Clojure también puede consultar las propiedades del sistema. A continuación se muestra un código de ejemplo.

Ejemplo

(ns Project
   (:gen-class))
(defn Example []
   (println (.. System getProperties (get "java.version"))))
(Example)

Dependiendo de la versión de Java en el sistema, se mostrará el valor correspondiente. A continuación se muestra un resultado de ejemplo.

Salida

1.8.0_45

En la programación de Clojure, la mayoría de los tipos de datos son inmutables, por lo que cuando se trata de programación concurrente, el código que utiliza estos tipos de datos es bastante seguro cuando el código se ejecuta en varios procesadores. Pero muchas veces, existe el requisito de compartir datos, y cuando se trata de datos compartidos entre múltiples procesadores, es necesario asegurarse de que el estado de los datos se mantenga en términos de integridad cuando se trabaja con múltiples procesadores. Esto se conoce comoconcurrent programming y Clojure proporciona soporte para dicha programación.

El sistema de memoria transaccional de software (STM), expuesto a través de dosync, ref, set, alter, etc., admite compartir el estado cambiante entre subprocesos de manera sincrónica y coordinada. El sistema de agentes admite el intercambio de estados cambiantes entre subprocesos de manera asincrónica e independiente. El sistema de átomos permite compartir el estado cambiante entre subprocesos de manera síncrona e independiente. Mientras que el sistema var dinámico, expuesto a través de def, binding, etc., admite el aislamiento de cambios de estado dentro de los hilos.

Otros lenguajes de programación también siguen el modelo de programación concurrente.

  • Tienen una referencia directa a los datos que se pueden modificar.

  • Si se requiere acceso compartido, el objeto se bloquea, el valor se cambia y el proceso continúa para el siguiente acceso a ese valor.

En Clojure no hay bloqueos, sino referencias indirectas a estructuras de datos persistentes inmutables.

Hay tres tipos de referencias en Clojure.

  • Vars - Los cambios se aíslan en hilos.

  • Refs - Los cambios se sincronizan y coordinan entre hilos.

  • Agents - Implica cambios independientes asincrónicos entre hilos.

Las siguientes operaciones son posibles en Clojure con respecto a la programación concurrente.

Actas

La concurrencia en Clojure se basa en transacciones. Las referencias solo se pueden cambiar dentro de una transacción. Las siguientes reglas se aplican en las transacciones.

  • Todos los cambios son atómicos y aislados.
  • Cada cambio en una referencia ocurre en una transacción.
  • Ninguna transacción ve el efecto de otra transacción.
  • Todas las transacciones se colocan dentro del bloque dosync.

Ya vimos lo que hace el bloque dosync, veámoslo de nuevo.

dosync

Ejecuta la expresión (en un do implícito) en una transacción que abarca la expresión y cualquier llamada anidada. Inicia una transacción si ninguna ya se está ejecutando en este hilo. Cualquier excepción no detectada abortará la transacción y saldrá de dosync.

A continuación se muestra la sintaxis.

Sintaxis

(dosync expression)

Parameters - 'expresión' es el conjunto de expresiones que vendrán en el bloque dosync.

Return Value - Ninguno.

Veamos un ejemplo en el que intentamos cambiar el valor de una variable de referencia.

Ejemplo

(ns clojure.examples.example
   (:gen-class))
(defn Example []
   (def names (ref []))
   (alter names conj "Mark"))
(Example)

Salida

El programa anterior cuando se ejecuta da el siguiente error.

Caused by: java.lang.IllegalStateException: No transaction running
   at clojure.lang.LockingTransaction.getEx(LockingTransaction.java:208)
   at clojure.lang.Ref.alter(Ref.java:173)
   at clojure.core$alter.doInvoke(core.clj:1866)
   at clojure.lang.RestFn.invoke(RestFn.java:443)
   at clojure.examples.example$Example.invoke(main.clj:5) at clojure.examples.example$eval8.invoke(main.clj:7)
   at clojure.lang.Compiler.eval(Compiler.java:5424)
   ... 12 more

En el error, puede ver claramente que no puede cambiar el valor de un tipo de referencia sin antes iniciar una transacción.

Para que el código anterior funcione, tenemos que colocar el comando alter en un bloque dosync como se hace en el siguiente programa.

Ejemplo

(ns clojure.examples.example
   (:gen-class))
(defn Example []
   (def names (ref []))
   
   (defn change [newname]
      (dosync
         (alter names conj newname)))
   (change "John")
   (change "Mark")
   (println @names))
(Example)

El programa anterior produce la siguiente salida.

Salida

[John Mark]

Veamos otro ejemplo de dosync.

Ejemplo

(ns clojure.examples.example
   (:gen-class))
(defn Example []
   (def var1 (ref 10))
   (def var2 (ref 20))
   (println @var1 @var2)
   
   (defn change-value [var1 var2 newvalue]
      (dosync
         (alter var1 - newvalue)
         (alter var2 + newvalue)))
   (change-value var1 var2 20)
   (println @var1 @var2))
(Example)

En el ejemplo anterior, tenemos dos valores que se están cambiando en un bloque dosync. Si la transacción es exitosa, ambos valores cambiarán; de lo contrario, toda la transacción fallará.

El programa anterior produce la siguiente salida.

Salida

10 20
-10 40

Clojure tiene algunas bibliotecas contribuidas que tienen la habilitación para crear Desktop y Web-based applications. Analicemos cada uno de ellos.

No Señor. Aplicaciones y descripción
1 Escritorio - balancín

See-saw es una biblioteca que se puede utilizar para crear aplicaciones de escritorio.

2 Escritorio: cambio del valor del texto

El valor del contenido en la ventana se puede cambiar usando el ‘config!’opción. En el siguiente ejemplo, config! La opción se usa para cambiar el contenido de la ventana al nuevo valor de "Adiós".

3 Escritorio: visualización de un cuadro de diálogo modal

Se puede mostrar un cuadro de diálogo modal mediante el método de alerta de la clase balancín. El método toma el valor de texto, que debe mostrarse en el cuadro de diálogo modal.

4 Escritorio: visualización de botones

Los botones se pueden mostrar con la ayuda de la clase de botón.

5 Escritorio: visualización de etiquetas

Las etiquetas se pueden mostrar con la ayuda de la clase de etiqueta.

6 Escritorio: visualización de campos de texto

Los campos de texto se pueden mostrar con la ayuda de la clase de texto.

Aplicaciones web - Introducción

Para crear una aplicación web en Clojure, debe utilizar la biblioteca de aplicaciones Ring, que está disponible en el siguiente enlace https://github.com/ring-clojure/ring

Debe asegurarse de descargar los archivos jar necesarios del sitio y asegurarse de agregarlos como una dependencia para la aplicación Clojure.

los Ring framework proporciona las siguientes capacidades:

  • Configura las cosas de manera que una solicitud http entra en su aplicación web como un Clojure HashMap normal, y también lo hace para que pueda devolver una respuesta como un HashMap.

  • Proporciona una especificación que describe exactamente cómo deberían verse esos mapas de solicitud y respuesta.

  • Trae un servidor web (Jetty) y conecta su aplicación web a él.

El marco Ring puede iniciar automáticamente un servidor web y garantiza que la aplicación Clojure funcione en este servidor. Entonces también se puede utilizar el marco Compojure. Esto permite crear rutas, que es ahora la forma en que se desarrollan la mayoría de las aplicaciones web modernas.

Creating your first Clojure application - El siguiente ejemplo muestra cómo puede crear su primera aplicación web en Clojure.

(ns my-webapp.handler
   (:require [compojure.core :refer :all]
      [compojure.route :as route]
      [ring.middleware.defaults :refer [wrap-defaults site-defaults]]))
(defroutes app-routes
   (GET "/" [] "Hello World")
   (route/not-found "Not Found"))
(def app
   (wrap-defaults app-routes site-defaults))

Veamos los siguientes aspectos del programa:

  • los ‘defroutes’ se utiliza para crear rutas de modo que la solicitud realizada a la aplicación web a diferentes rutas se pueda dirigir a diferentes funciones en su aplicación Clojure.

  • En el ejemplo anterior, la "/" se conoce como la ruta predeterminada, por lo que cuando navega a la base de su aplicación web, la cadena "Hello World" se enviará al navegador web.

  • Si el usuario ingresa a cualquier URL que no pueda ser procesada por la aplicación Clojure, entonces mostrará la cadena "No encontrado".

Cuando ejecuta la aplicación Clojure, de manera predeterminada, su aplicación se cargará como localhost: 3000, por lo que si navega hasta esta ubicación, recibirá el siguiente resultado.

Aplicaciones web: agregar más rutas a su aplicación web

También puede agregar más rutas a su aplicación web. El siguiente ejemplo muestra cómo lograrlo.

(ns my-webapp.handler
   (:require [compojure.core :refer :all]
      [compojure.route :as route]
      [ring.middleware.defaults :refer [wrap-defaults site-defaults]]))
(defroutes app-routes
   (GET "/" [] "Hello World")
   (GET "/Tutorial" [] "This is a tutorial on Clojure")
   (route/not-found "Not Found"))
(def app
   (wrap-defaults app-routes site-defaults))

Puede ver que agregar una ruta en la aplicación es tan fácil como agregar otra función GET con la ruta URL. (OBTENER "/ Tutorial" [] "Este es un tutorial sobre Clojure")

Si navega hasta la ubicación http://localhost:3000/Tutorial, recibirá el siguiente resultado.

En este capítulo, analicemos las opciones de prueba automatizadas proporcionadas por Clojure.

Pruebas para aplicaciones cliente

Para usar las pruebas para el marco Clojure, debe usar las dependencias ubicadas en https://github.com/slagyr/speclj#manual-installation

Esta URL proporciona la specljframework, que se utiliza como un marco de prueba basado en datos de prueba o basado en comportamiento para Clojure. Debe asegurarse de usar el marco Clojure 1.7.0 cuando use cualquiera de las bibliotecas 'speclj'. De forma predeterminada, los archivos de prueba serán diferentes de los archivos de código de Clojure y deben colocarse en un directorio de 'especificaciones'.

A continuación se muestra un código de muestra para un archivo de prueba.

(ns change.core-spec
   (:require [speclj.core :refer :all]))
(describe "Truth"
   (it "is true"
   (should true))
   (it "is not false"
   (should-not false)))
(run-specs)

Se deben tener en cuenta las siguientes cosas sobre el código anterior:

  • Primero tenemos que asegurarnos de usar la declaración 'require' para incluir todas las bibliotecas centrales en el marco 'speclj'.

  • Lo siguiente es la función 'describir'. Se utiliza para proporcionar una descripción del caso de prueba que se está creando.

  • La siguiente función es la función 'it', que es el caso de prueba real. En el primer caso de prueba, la cadena "es verdadero" es el nombre dado al caso de prueba.

  • Debería y no debería conocerse como assertions. Todas las afirmaciones comienzan con should. Debería y no debería son solo dos de las muchas afirmaciones disponibles. Ambos toman expresiones que verificarán la veracidad y falsedad respectivamente.

Si ejecuta el caso de prueba, obtendrá el siguiente resultado. La salida muestra el tiempo en milisegundos para que se ejecute el caso de prueba.

←[32m.←[0m←[32m.←[0m
Finished in 0.00014 seconds

Prueba de aplicaciones basadas en web

Seleniumes uno de los marcos clave utilizados para probar aplicaciones modernas basadas en web. Las bibliotecas de Clojure también están disponibles y pueden usarse para probar aplicaciones basadas en web.

Veamos cómo podemos usar las bibliotecas de Selenium para probar aplicaciones basadas en web de Clojure.

Step 1- El primer paso es asegurarnos de que estamos usando el marco Ring and Compojure para crear una aplicación basada en la web, que debe probarse. Usemos uno de los ejemplos de nuestros capítulos anteriores. El siguiente código es una aplicación web simple, que muestra "Hello World" en el navegador.

(ns my-webapp.handler
   (:require [compojure.core :refer :all]
      [compojure.route :as route]
      [ring.middleware.defaults :refer [wrap-defaults site-defaults]]))
(defroutes app-routes
   (GET "/" [] "Hello World")
   (route/not-found "Not Found"))
(def app
   (wrap-defaults app-routes site-defaults))

Step 2 - A continuación, asegúrese de descargar el archivo jar de selenio https://mvnrepository.com/artifact/org.seleniumhq.selenium/selenium-server/2.47.0 e inclúyalo en su classpath.

Step 3 - Asegúrese también de descargar el controlador web 'clj', que se utilizará para ejecutar la prueba web desde la siguiente ubicación.

https://clojars.org/clj-webdriver/versions/0.7.1

Step 4 - En el directorio de su proyecto, cree otro directorio llamado características y cree un archivo llamado 'config.clj'.

Step 5 - A continuación, agregue el siguiente código al archivo 'config.clj' creado en el paso anterior.

ns clj-webdriver-tutorial.features.config)
(def test-port 3000)
(def test-host "localhost")
(def test-base-url (str "http://" test-host ":" test-port "/"))

El código anterior básicamente le dice al marco de prueba web que pruebe la aplicación, que se carga en la URL http://localhost:3000

Step 6 - Por último, escribamos nuestro código para realizar nuestra prueba.

(ns clj-webdriver-tutorial.features.homepage
   (:require [clojure.test :refer :all]
      [ring.adapter.jetty :refer [run-jetty]]
      [clj-webdriver.taxi :refer :all]
      [clj-webdriver-tutorial.features.config :refer :all]
      [clj-webdriver-tutorial.handler :refer [app-routes]]))
(ns clj-webdriver-tutorial.features.homepage
   (:require [clojure.test :refer :all]
      [ring.adapter.jetty :refer [run-jetty]]
      [clj-webdriver.taxi :refer :all]
      [clj-webdriver-tutorial.features.config :refer :all]
      [clj-webdriver-tutorial.handler :refer [app-routes]]))
(defn start-server []
   (loop [server (run-jetty app-routes {:port test-port, :join? false})]
      (if (.isStarted server)
         server
         (recur server))))
(defn stop-server [server]
   (.stop server))
(defn start-browser []
   (set-driver! {:browser :firefox}))
(defn stop-browser []
   (quit))
(deftest homepage-greeting
   (let [server (start-server)]
      (start-browser)
      (to test-base-url)
      (is (= (text "body") "Hello World"))
      (stop-browser)
      (stop-server server)))

El código anterior llevará a cabo las siguientes acciones:

  • Inicie el servidor de la aplicación.
  • Abra la ruta raíz en el navegador.
  • Compruebe si el mensaje "Hola mundo" está presente en la página.
  • Cierre el navegador.
  • Apague el servidor.

Una cosa que hace que la biblioteca Clojure sea tan poderosa es la cantidad de bibliotecas disponibles para el marco Clojure. Ya hemos visto tantas bibliotecas utilizadas en nuestros ejemplos anteriores para pruebas web, desarrollo web, desarrollo de aplicaciones basadas en swing, la biblioteca jdbc para conectarse a bases de datos MySQL. A continuación se muestran solo un par de ejemplos de algunas bibliotecas más.

data.xml

Esta biblioteca permite a Clojure trabajar con datos XML. La versión de la biblioteca que se utilizará es org.clojure / data.xml "0.0.8". El archivo data.xml admite el análisis y la emisión de XML. Las funciones de análisis leerán XML de un Reader o InputStream.

Ejemplo

A continuación se muestra un ejemplo del procesamiento de datos de una cadena a XML.

(ns clojure.examples.example
   (use 'clojure.data.xml)
   (:gen-class))
(defn Example []
   (let [input-xml (java.io.StringReader. "<?xml version = \"1.0\"
      encoding = \"UTF-8\"?><example><clo><Tutorial>The Tutorial
      value</Tutorial></clo></example>")]
      (parse input-xml)))

#clojure.data.xml.Element{
   :tag :example, :attrs {}, :content (#clojure.data.xml.Element {
      :tag :clo, :attrs {}, :content (#clojure.data.xml.Element {
         :tag :Tutorial, :attrs {},:content ("The Tutorial value")})})}
(Example)

data.json

Esta biblioteca permite que Clojure funcione con datos JSON. La versión de la biblioteca que se utilizará es org.clojure / data.json "0.2.6".

Ejemplo

A continuación se muestra un ejemplo sobre el uso de esta biblioteca.

(ns clojure.examples.example
   (:require [clojure.data.json :as json])
   (:gen-class))
(defn Example []
   (println (json/write-str {:a 1 :b 2})))
(Example)

Salida

El programa anterior produce la siguiente salida.

{\"a\":1,\"b\":2}

data.csv

Esta biblioteca permite que Clojure funcione con ‘csv’datos. La versión de la biblioteca que se utilizará es org.clojure / data.csv "0.1.3".

Ejemplo

A continuación se muestra un ejemplo sobre el uso de esta biblioteca.

(ns clojure.examples.example
   (require '[clojure.data.csv :as csv]
      '[clojure.java.io :as io])
   (:gen-class))
(defn Example []
   (with-open [in-file (io/reader "in-file.csv")]
      (doall
      (csv/read-csv in-file)))
   (with-open [out-file (io/writer "out-file.csv")]
   (csv/write-csv out-file
      [[":A" "a"]
      [":B" "b"]])))
(Example)

En el código anterior, la función 'csv' leerá primero un archivo llamado in-file.csvy poner todos los datos en la variable en el archivo. A continuación, estamos usando la función write-csv para escribir todos los datos en un archivo llamadoout-file.csv.