Olmo - Guía rápida

Elm es un lenguaje de programación funcional. Fue diseñado por Evan Czaplicki en 2012.

Elm se utiliza específicamente para diseñar aplicaciones web.

Elm se compila en JavaScript y se ejecuta en el navegador. Es rápido, comprobable, fácil de mantener y no incluye excepciones en tiempo de ejecución.

Algunas aplicaciones prácticas de la plataforma de programación Elm incluyen:

  • Games
  • Graphics
  • Aplicaciones de una sola página

Por qué Elm

Elm elimina la mayoría de los problemas comunes que enfrentan los desarrolladores frontend. Esto incluye:

Sin excepciones en tiempo de ejecución

Elm es un lenguaje escrito estáticamente. Todos los posibles errores se validan y corrigen en tiempo de compilación. Esto hace posible que no haya excepciones en tiempo de ejecución.

Mensajes de error amigables para desarrolladores

A diferencia de otros lenguajes de programación, el compilador de Elm está diseñado para proporcionar mensajes de error muy específicos y fáciles de usar para los desarrolladores en tiempo de compilación. Los mensajes de error también incluyen sugerencias como enlaces a la documentación de diseño recomendada.

Fácil de probar

Cada función de Elm se puede probar aisladamente de todas las demás. Esto hace que los programas escritos en Elm sean fácilmente comprobables.

Control de versiones semántico automático

Elm impone el control de versiones semántico automático de los paquetes. Esto garantiza que un cambio de parche no bloquee una aplicación que ya se esté ejecutando.

Código reutilizable

Las funciones de Elm son intrínsecamente fáciles de reutilizar en comparación con las funciones de JavaScript, Python o TypeScript.

Este capítulo analiza los pasos para instalar Elm en plataformas Windows, Mac y Linux.

Configuración del entorno local

Considere los pasos que se muestran a continuación para instalar Elm en su entorno local.

Step 1 − Install node

Dado que elm está compilado en JavaScript, la máquina de destino debería tener nodeinstalado. Consulte el curso TutorialsPoint NodeJS para conocer los pasos para configurarnode y npm

Configuración de nodo.

Step 2 − Install elm

Ejecute el siguiente comando en el terminal para instalar elm. Tenga en cuenta que la versión estable de elm era 0.18 al momento de escribir este curso.

npm install -g [email protected]

Después de la instalación, ejecute el siguiente comando para verificar la versión de Elm.

C:\Users\dell>elm --version
0.18.0

Step 2 − Install the Editor

El entorno de desarrollo utilizado aquí es Visual Studio Code (plataforma Windows).

Visual Studio Code es un IDE de código abierto de Visual Studio. Está disponible para plataformas Mac OS X, Linux y Windows. VSCode está disponible en

Instalación en Windows

En esta sección, analizaremos los pasos para instalar Elm en Windows.

Descargar https://code.visualstudio.com/. para ventanas.

Haga doble clic en VSCodeSetup.exe para iniciar el proceso de instalación. Esto solo tomará un minuto.

Puede ir directamente a la ruta del archivo haciendo clic con el botón derecho en Archivo → Abrir en el símbolo del sistema. De manera similar, la opción Revelar en el Explorador muestra el archivo en el Explorador de archivos.

Instalación en Mac OS X

La guía de instalación específica de Mac OS X de Visual Studio Code se puede encontrar en Instalación de VSCode-MAC.

Instalación en Linux

La guía de instalación específica de Linux de Visual Studio Code se puede encontrar en Instalación de VSCode-Linux.

Step 4 − Install the elm Extension

Instale la extensión elm en VSCode como se muestra a continuación.

Olmo REPL

REPL son las siglas de Read Eval Print Loop. Representa un entorno informático como una consola de Windows o un shell de Unix / Linux donde se ingresa un comando y el sistema responde con una salida en un modo interactivo.

Elm viene con un entorno REPL. Realiza las siguientes tareas:

  • Leer: lee la entrada del usuario, analiza la entrada en la estructura de datos de elm y la almacena en la memoria.

  • Eval: toma y evalúa la estructura de datos.

  • Imprimir: imprime el resultado.

  • Bucle: repite el comando anterior hasta que el usuario sale. Use el comando: salir para salir de REPL y regresar a la terminal.

A continuación se muestra un ejemplo simple para sumar dos números en REPL:

Abra la terminal VSCode y escriba el comando elm REPL.

El terminal REPL espera que el usuario ingrese alguna entrada. Ingrese la siguiente expresión 10 + 20. El entorno REPL procesa la entrada como se indica a continuación:

  • Lee los números 10 y 20 del usuario.

  • Evalúa usando el operador +.

  • Las impresiones resultan como 30.

  • Bucles para la siguiente entrada del usuario. Aquí salimos del bucle.

Este capítulo trata sobre cómo escribir un programa simple en elm.

Step 1 − Create a directory HelloApp in VSCode

Ahora, crea un archivo - Hello.elm en este directorio.

El diagrama de arriba muestra la carpeta del proyecto HelloApp y terminal abierto en VSCode.

Step 2 − Install the necessary elm packages

El administrador de paquetes en elm es elm-package . Instale el paquete elm-lang / html . Este paquete nos ayudará a mostrar la salida del código elm en el navegador.

Atravesar al HelloApp carpeta del proyecto haciendo clic derecho en Archivo → Abrir en el símbolo del sistema en VSCode.

Ejecute el siguiente comando en la ventana del terminal:

C:\Users\dell\Elm\HelloApp> elm-package install elm-lang/html

Los siguientes archivos / carpetas se agregan al directorio del proyecto al instalar el paquete.

  • elm-package.json (archivo), almacena metadatos del proyecto
  • elm-stuff (carpeta), almacena paquetes externos

El siguiente mensaje aparecerá una vez que el paquete se haya instalado correctamente.

Step 3 − Add the following code to the Hello.elm file

-- importing Html module and the function text
import Html exposing (text)

-- create main method
main =
-- invoke text function
text "Hello Elm from TutorialsPoint"

El programa anterior mostrará un mensaje de cadena Hello Elm from TutorialsPoint en el navegador.

Para esto, necesitamos importar la función text dentro de Htmlmódulo. La función de texto se utiliza para imprimir cualquier valor de cadena en el navegador. El método principal es el punto de entrada a un programa. El método principal invoca la función de texto y le pasa un valor de cadena.

Step 4 − Compile the project

Ejecute el siguiente comando en la ventana del terminal VSCode.

elm make Hello.elm

La salida del comando anterior es como se muestra a continuación:

//update path to the proj folder in the command elm make
C:\Users\dell\elm\HelloApp>elm make Hello.elm
Success! Compiled 38 modules.
Successfully generated index.html

El comando anterior generará un index.htmlarchivo. El compilador de elm convierte el archivo .elm a JavaScript y lo incrusta en elindex.html archivo.

Step 5 − Open the index.html in the browser

Abra el archivo index.html en cualquier navegador. La salida será como se muestra a continuación:

Comentarios en Elm

Los comentarios son una forma de mejorar la legibilidad de un programa. Los comentarios se pueden utilizar para incluir información adicional sobre un programa, como el autor del código, sugerencias sobre la construcción de una función, etc. El compilador ignora los comentarios.

Elm admite los siguientes tipos de comentarios:

  • Comentarios de una sola línea (-): cualquier texto entre un - y el final de una línea se trata como un comentario.

  • Comentarios de varias líneas ({- -}): estos comentarios pueden abarcar varias líneas.

Ilustración

-- this is single line comment

{- This is a
   Multi-line comment
-}

Líneas y sangría

Elm no proporciona llaves para indicar bloques de código para definiciones de funciones o control de flujo. Los bloques de código se indican mediante sangría de línea, que se aplica de forma rígida. Todas las declaraciones dentro de un bloque deben tener la misma sangría. Por ejemplo

module ModuleIf exposing (..)
x = 0

function1 =
   if x > 5 then
      "x is greater"
   else
      "x is small"

Sin embargo, el siguiente bloque genera un error:

-- Create file ModuleIf.elm
module ModuleIf exposing (..)
x = 0

function1 =
   if x > 5 then
      "x is greater"
         else --Error:else indentation not at same level of if statement
      "x is small"

Así, en Elm todas las líneas continuas sangradas con el mismo número de espacios formarían un bloque.

C:\Users\admin>elm repl
---- elm-repl 0.18.0 -----------------------------------------------------------
   :help for help, :exit to exit, more at 
   <https://github.com/elm-lang/elm-repl>
   ---------------------------------------
   -----------------------------------------

> import ModuleIf exposing(..) -- importing module from ModuleIf.elm file
>function1 -- executing function from module
-- SYNTAX PROBLEM ---------------------------------------------------

I need whitespace, but got stuck on what looks like a new declaration. 
You are either missing some stuff in the declaration above or just need to add some spaces here:
7| else
   ^
I am looking for one of the following things:

   whitespace

El sistema de tipos representa los diferentes tipos de valores admitidos por el idioma. El Type System verifica la validez de los valores proporcionados, antes de que sean almacenados o manipulados por el programa. Esto asegura que el código se comporte como se esperaba. Además, el Type System permite sugerencias de código más completas y documentación automatizada.

Elm es un lenguaje escrito estáticamente. Elm tiene tipos similares a los de otros idiomas.

Número

El número de tipo de datos representa valores numéricos. El sistema de tipo Elm admite los siguientes tipos numéricos:

No Señor. Tipo Ejemplo
1 número: almacena cualquier número 7 es el tipo de número
2 Flotante: almacena valores fraccionarios 7/2 da un resultado de 3,5 como flotante
3 Int: almacena valores no fraccionarios 7 // 2 da 3 resultado como Int

El número de tipo admite valores fraccionarios y no fraccionarios. Abra el elm REPL y pruebe los ejemplos que se dan a continuación:

C:\Users\admin>elm repl
---- elm-repl 0.18.0 
---------------------------------------------
--------------
:help for help, :exit to exit, more at <https://github.com/elm-lang/elm-repl>
------------------------------------------
--------------------------------------
> 7
7 : number
> 7/2
3.5 : Float
> 7//2
3 : Int
>

Cadena y Char

El tipo de datos String se utiliza para representar una secuencia de caracteres. El tipo de datos Char se utiliza para representar un solo carácter. Los valores de cadena se definen entre comillas dobles "y los valores de Char están encerrados entre comillas simples".

No Señor. Tipo Ejemplo
1 Cadena: almacena una secuencia de caracteres "TutorialsPoint"
2 Char: almacena valores fraccionarios 'T'

Abra el elm REPL y pruebe los ejemplos que se dan a continuación:

C:\Users\admin>elm repl
---- elm-repl 0.18.0 ---------------------------------------
--------------------
:help for help, :exit to exit, more at <https://github.com/elm-lang/elm-repl>
--------------------------------------
------------------------------------------
> "TutorialsPoint"
"TutorialsPoint" : String
> 'T'
'T' : Char

Bool

El tipo de datos Bool en Elm solo admite dos valores: Verdadero y Falso. La palabra clave Bool se utiliza para representar un valor booleano.

No Señor. Tipo Ejemplo
1 Bool: almacena valores verdadero o falso 1 == 1 devuelve verdadero

Abra el elm REPL y pruebe los ejemplos que se dan a continuación:

C:\Users\dell\elm>elm repl
---- elm-repl 0.18.0 -----------------------------------
------------------------
:help for help, :exit to exit, more at <https://github.com/elm-lang/elm-repl>
----------------------------------------
----------------------------------------
> True
True : Bool
> False
False : Bool
> 1==1
True : Bool
> 1==2
False : Bool
> 1 /= 2 -- not equal
True : Bool
> not True
False : Bool
> not False
True : Bool

Tipos personalizados

Elm admite la creación de tipos definidos por el usuario. Por ejemplo, considere una aplicación de pago. La aplicación necesita almacenar diferentes modos de pago: tarjeta de crédito, tarjeta de débito y banca neta. Esto se puede lograr definiendo un tipo personalizado y restringiendo su valor a los tres modos de pago aceptables.

El siguiente ejemplo muestra cómo hacer un tipo personalizado.

> type PaymentMode = CreditCard|NetBanking|DebitCard
> payment1 = CreditCard
CreditCard : Repl.PaymentMode
> payment2 = DebitCard
DebitCard : Repl.PaymentMode
> payment3 = UPI
-- NAMING ERROR ---------------------------------------------- repl-temp-000.elm

Cannot find variable `UPI`

7| payment3 = UPI

En el ejemplo anterior, creamos un tipo personalizado PaymentMode. Las variables pago1 y pago2 se asignan a los valores de PaymentMode. Si el valor asignado a la variable no coincide con ninguno de los valores definidos por el tipo PaymentMode, la aplicación arrojará un error de sintaxis.

Tipos de datos estructurados

Los tipos de datos estructurados se pueden utilizar para almacenar varios valores en un formato estructurado. Elm admite los siguientes tipos de datos estructurados:

  • Tuple
  • List
  • Record
  • Record

Estos se discutirán en detalle en los próximos capítulos.

Una variable, por definición, es "un espacio con nombre en la memoria" que almacena valores. En otras palabras, actúa como un contenedor de valores en un programa. Una variable ayuda a los programas a almacenar y manipular valores.

Las variables en Elm están asociadas con un tipo de datos específico. El tipo de datos determina el tamaño y el diseño de la memoria de la variable, el rango de valores que se pueden almacenar dentro de esa memoria y el conjunto de operaciones que se pueden realizar en la variable.

Reglas de denominación de variables

En esta sección, aprenderemos sobre las reglas de denominación de variables.

  • Los nombres de las variables pueden estar compuestos por letras, dígitos y el carácter de subrayado.
  • Los nombres de las variables no pueden comenzar con un dígito. Debe comenzar con una letra o un guión bajo.
  • Las letras mayúsculas y minúsculas son distintas porque Elm distingue entre mayúsculas y minúsculas.

Declaración de variable en Elm

La sintaxis de tipo para declarar una variable en Elm se da a continuación:

Sintaxis 1

variable_name:data_type = value

La sintaxis “:” (conocida como anotación de tipo) se utiliza para asociar la variable con un tipo de datos.

Sintaxis 2

variable_name = value-- no type specified

El tipo de datos es opcional al declarar una variable en Elm. En este caso, el tipo de datos de la variable se infiere del valor que se le asigna.

Ilustración

Este ejemplo usa el editor VSCode para escribir un programa elm y ejecutarlo usando elm repl.

Step 1 − Create a project folder - VariablesApp. Create a Variables.elm file in the project folder.

Agregue el siguiente contenido al archivo.

module Variables exposing (..) //Define a module and expose all contents in the module
message:String -- type annotation
message = "Variables can have types in Elm"

El programa define un módulo Variables. El nombre de un módulo debe ser el mismo que el del archivo de programa elm. La sintaxis (..) se utiliza para exponer todos los componentes del módulo.

El programa declara un mensaje variable del tipo String .

Step 2 − Execute the program.

  • Escriba el siguiente comando en la terminal VSCode para abrir elm REPL.
elm repl
  • Ejecute la siguiente declaración de elm en la terminal REPL.
> import Variables exposing (..) --imports all components from the Variables module
> message --Reads value in the message varaible and prints it to the REPL 
"Variables can have types in Elm":String
>

Ilustración

Utilice Elm REPL para probar el siguiente ejemplo.

C:\Users\dell\elm>elm repl
---- elm-repl 0.18.0 ---------------------------------------
--------------------
:help for help, :exit to exit, more at <https://github.com/elm-lang/elm-repl>
-------------------------------------
------------------------------------------
> company = "TutorialsPoint"
"TutorialsPoint" : String
> location = "Hyderabad"
"Hyderabad" : String
> rating = 4.5
4.5 : Float

Aquí, las variables empresa y ubicación son variables de cadena y la calificación es una variable flotante.

Elm REPL no admite anotaciones de tipo para variables. El siguiente ejemplo arroja un error si se incluye el tipo de datos al declarar una variable.

C:\Users\dell\elm>elm repl
---- elm-repl 0.18.0 -----------------------------------------
------------------
:help for help, :exit to exit, more at <https://github.com/elm-lang/elm-repl>
----------------------------------------
----------------------------------------
> message:String
-- SYNTAX PROBLEM -------------------------------------------- repl-temp-000.elm

A single colon is for type annotations. Maybe you want :: instead? Or maybe you
are defining a type annotation, but there is whitespace before it?

3| message:String
^

Maybe <http://elm-lang.org/docs/syntax> can help you figure it out.

Para insertar un salto de línea mientras usa elm REPL, use la sintaxis \ como se muestra a continuación:

C:\Users\dell\elm>elm repl
---- elm-repl 0.18.0 --------------------------------------
---------------------
:help for help, :exit to exit, more at <https://github.com/elm-lang/elm-repl>
------------------------------------------
--------------------------------------
> company \ -- firstLine
| = "TutorialsPoint" -- secondLine
"TutorialsPoint" : String

Un operador define alguna función que se realizará en los datos. Los valores sobre los que trabajan los operadores se denominan operandos. Considere la siguiente expresión

7 + 5 = 12

Aquí, los valores 7, 5 y 12 son operandos, mientras que + y = son operadores.

Los principales operadores en Elm se pueden clasificar como:

  • Arithmetic
  • Relational
  • Logical

Operadores aritméticos

Suponga que los valores de las variables ayb son 7 y 2 respectivamente.

Mostrar ejemplos

No Señor. Operador Descripción Ejemplo
1 + (Adición) devuelve la suma de los operandos a + b es 9
2 -(Sustracción) devuelve la diferencia de los valores ab es 5
3 * (Multiplicación) devuelve el producto de los valores a * b es 14
4 / (División flotante) realiza la operación de división y devuelve un cociente flotante a / b es 3,5
5 //(División entera) realiza la operación de división y devuelve un cociente entero a // b es 3
6 % (Módulo) realiza la operación de división y devuelve el resto a% b es 1

Operadores relacionales

Los operadores relacionales prueban o definen el tipo de relación entre dos entidades. Estos operadores se utilizan para comparar dos o más valores. Los operadores relacionales devuelven un valor booleano, es decir, verdadero o falso.

Suponga que el valor de a es 10 y b es 20.

Mostrar ejemplos

No Señor. Operador Descripción Ejemplo
1 > Mas grande que (a> b) es falso
2 < Menor que (a <b) es verdadero
3 > = Mayor qué o igual a (a> = b) es falso
4 <= Menor o igual a (a <= b) es verdadero
5 == Igualdad (a == b) es falso
6 ! = No es igual (a! = b) es verdadero

Tipos comparables

Los operadores de comparación como> = o <funcionan con tipos comparables. Estos se definen como números, caracteres, cadenas y listas, tuplas. Los tipos comparables en ambos lados del operador deben ser los mismos.

No Señor. Tipo comparable Ejemplo
1 número 7> 2 da Verdadero
2 personaje 'a' == 'b' da Falso
3 cuerda "hola" == "hola" da True
4 tupla (1, "Uno") == (1, "Uno") da Verdadero
5 lista [1,2] == [1,2] da verdadero

Abra el elm REPL y pruebe los ejemplos que se muestran a continuación:

C:\Users\admin>elm repl
---- elm-repl 0.18.0 -----------------------------------------------------------
:help for help, :exit to exit, more at <https://github.com/elm-lang/elm-repl>
--------------------------------------------------------------------------------
> 7>2
True : Bool
> 7.0>2
True : Bool
> 7.0<2.0
False : Bool
> 'a' > 'b'
False : Bool
> 'a' < 'b'
True : Bool
> "a" < "b"
True : Bool
> (1,2) > (2,3)
False : Bool
> ['1','3'] < ['2','1']
True : Bool
>

Operadores logicos

Los operadores lógicos se utilizan para combinar dos o más condiciones. Los operadores lógicos también devuelven un valor booleano.

Mostrar ejemplos

No Señor. Operador Descripción Ejemplo
1 && El operador devuelve verdadero solo si todas las expresiones especificadas devuelven verdadero (10> 5) && (20> 5) devuelve verdadero
2 || El operador devuelve verdadero si al menos una de las expresiones especificadas devuelve verdadero (10 <5) || (20> 5) devuelve verdadero
3 no El operador devuelve el resultado inverso de la expresión. Por ejemplo:! (> 5) devuelve falso. not (10 <5) devuelve verdadero
4 xor El operador devuelve verdadero solo si exactamente una entrada devuelve verdadero. El operador devuelve falso si ambas expresiones devuelven verdadero. xor (10> 5) (20> 5) devuelve falso

Las estructuras de toma de decisiones requieren 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 el se determina que la condición es falsa.

A continuación se muestra la forma general de una estructura típica de toma de decisiones que se encuentra en la mayoría de los lenguajes de programación.

Una construcción de toma de decisiones evalúa una condición antes de que se ejecuten las instrucciones. Los constructos de toma de decisiones en Elm se clasifican de la siguiente manera:

No Señor. Declaración Descripción
1 si ... entonces ... declaración else La instrucción if consiste en una expresión booleana seguida de then, que se ejecuta si la expresión devuelve verdadero y de lo contrario, se ejecuta si la expresión devuelve falso
2 declaración if anidada Puedes usar uno si ... entonces ... else dentro de otro si.
3 declaración de caso Prueba el valor de una variable con una lista de valores.

if ... then ... else Statement

los if…thenconstructo evalúa una condición antes de que se ejecute un bloque de código. Si la expresión booleana se evalúa como verdadera, entonces se ejecutará el bloque de código dentro de la declaración then. Si la expresión booleana se evalúa como falsa, se ejecutará el bloque de código dentro de la instrucción else.

A diferencia de otros lenguajes de programación, en Elm debemos proporcionar la rama else. De lo contrario, Elm arrojará un error.

Sintaxis

if boolean_expression then statement1_ifTrue else statement2_ifFalse

Ilustración

Pruebe el siguiente ejemplo en el terminal REPL.

> if 10>5 then "10 is bigger" else "10 is small"
"10 is bigger" : String

Anidado si

La instrucción if anidada es útil para probar varias condiciones. La sintaxis de una instrucción if anidada se da a continuación:

if boolean_expression1 then statement1_ifTrue else if boolean_expression2 then statement2_ifTrue else statement3_ifFalse

Ilustración

Pruebe el siguiente ejemplo en Elm REPL:

> score=80
80 : number
> if score>=80 then "Outstanding" else if score > = 70 then "good" else "average"
"Outstanding" : String

Declaración de caso

La declaración del caso se puede utilizar para simplificar la declaración if then else. La sintaxis de una declaración de caso es la siguiente:

case variable_name of
   constant1 -> Return_some_value
   constant2 -> Return_some_value
   _ -> Return_some_value if none of the above values match

La declaración de caso comprueba si el valor de una variable coincide con un conjunto predefinido de constantes y devuelve el valor correspondiente. Tenga en cuenta que el valor devuelto por cada caso debe ser del mismo tipo. Si el valor de las variables no coincide con ninguna de las constantes dadas, el control se pasa a * predeterminado * (indicado por // _) y se devuelve el valor correspondiente.

Ilustración

Pruebe el siguiente ejemplo en Elm REPL:

> n = 10
10 : number
> case n of \
| 0 -> "n is Zero" \
| _ -> "n is not Zero"
"n is not Zero" : String

El fragmento de código anterior comprueba si el valor de n es cero. El control pasa al valor predeterminado, que devuelve la cadena "n no es cero".

Elm es un lenguaje de programación funcional. Elm utiliza el concepto de recursividad como alternativa a las construcciones de bucle tradicionales.

Este capítulo analiza el concepto de recursividad.

Recursividad

Algunos lenguajes de programación de computadoras permiten que un módulo o función se llame a sí mismo. Esta técnica se conoce como recursividad.

Ilustración

En este programa, veremos cómo usar la recursividad para mostrar hola cinco veces.

Step 1 − Create a file Loop.elm

Crear un bucle de módulo y definir una función sayHello. La función sayHello toma un valor entero como entrada y devuelve un valor de cadena.

module Loop exposing(..)
//function signature
sayHello:Int ->String
//function implementation
sayHello n =
   case n of
   1 -> "Hello:1 "
   _ -> "Hello:" ++ toString (n) ++ " " ++ sayHello(n-1)

La función sayHello comprueba si el parámetro pasado es 1. Si el parámetro es 1, la función regresará, de lo contrario creará una cadena Hello y llamará a la misma función.

Step 2 − Invoke sayHello from REPL

Abra el elm REPL de la carpeta del proyecto actual (ubicación del archivo Loop.elm).

//import the module Loop
> import Loop exposing(..)
//invoke the sayHello function with parameter value as 5
> sayHello 5
"Hello:5 Hello:4 Hello:3 Hello:2 Hello:1 Hello:0 " : String
>

Ilustración

El siguiente ejemplo imprime la suma de n números usando recursividad.

> sumOfNos n =\
| if n==0 then 0 \
| else (n) + sumOfNos (n-1)
<function> : number -> number1

En elm REPL, creamos una función sumOfNos que toma un número de entrada y suma todos los números de 0 a ese número.

Por ejemplo, si pasamos la entrada como 5, sumará 1 + 2 + 3 + 4 + 5 que es 15 .

> ssumOfNos 5
15 : number

La salida del programa se muestra arriba.

Las funciones son los componentes básicos de un programa de Elm. Una función es un conjunto de declaraciones para realizar una tarea específica.

Las funciones organizan el programa en bloques lógicos de código. Una vez definidas, las funciones se pueden llamar para acceder al código. Esto hace que el código sea reutilizable. Además, las funciones facilitan la lectura y el mantenimiento del código del programa.

Pasos para usar una función

Hay tres pasos para usar una función:

Declaración de función

Una declaración de función le dice al compilador sobre el nombre, el tipo de retorno y los parámetros de una función. La sintaxis para declarar una función se da a continuación:

fn_name:data_type_of_the_parameters ->return_type

La declaración de función especifica lo siguiente:

  • Nombre de la función.

  • Tipo de datos de los parámetros. Esto es opcional ya que una función puede tener parámetros o no.

  • Tipo de datos del valor que devolverá la función. Las funciones en Elm siempre deben devolver un valor, ya que Elm es un lenguaje de programación funcional. A diferencia de las funciones de otros lenguajes de programación, las funciones de Elm no utilizan la palabra clave return para devolver un valor.

Definición de función o implementación de función

Una definición de función proporciona el cuerpo real de la función. Una definición de función especifica cómo se haría una tarea específica. La sintaxis para definir una función es la siguiente:

fn_name parameter1 parameter2 = statements

Invocar o llamar a una función

Se debe llamar a una función para ejecutarla. La sintaxis para llamar a una función se da a continuación:

fn_name parameter1 parameter2

Ilustración

El siguiente código define una función saludar. La función devuelve una cadena "Hola".

> greet = \
| if True then \
| "Hello" \
| else \
| "GoodBye"
"Hello" : String
> greet
"Hello" : String

Funciones parametrizadas

Los parámetros son un mecanismo para pasar valores a una función. Los valores de los parámetros se pasan a la función en el momento de la invocación de la función.

Ilustración 1

El siguiente ejemplo define una función fn_add . La función acepta dos números como parámetros y devuelve su suma. Pruebe lo siguiente en elm REPL:

> fn_add x y = x+y
<function> : number -> number -> number
> fn_add 10 20
30 : number

Ilustración 2

El siguiente ejemplo define una función sayHello. La función sayHello acepta y devuelve un valor de cadena como parámetro y devuelve una cadena.

> sayHello name = "Hello "++ name
<function> : String -> String
> sayHello "Tutorialspoint"
"Hello Tutorialspoint" : String
>

Operador de tubería

Para entender el operador de tubería |>, consideremos un ejemplo en el que tenemos una lista de cadenas diferentes ["a", "b", "c"] . Ahora necesitamos una sola cadena, que está separada por -

El siguiente ejemplo muestra cómo hacer eso con String.join

> String.join "-" ["a","b","c","d","e","f"]
"a-b-c-d-e-f" : String

La misma acción se puede realizar utilizando un operador de tubería |>. El operador de tubería se puede utilizar para encadenar múltiples llamadas a funciones.

> ["a","b","c","d","e","f"] |> String.join "-"
"a-b-c-d-e-f" : String
> ["a","b","c","d","e","f"] |> List.reverse |> String.join "-"
"f-e-d-c-b-a" : String

En el primer ejemplo, estamos encadenando la lista al método de unión. En el segundo caso, la misma lista se canaliza para invertir la función y luego se canaliza para unirse. Entonces, la lista se muestra invertida y unida.

Una secuencia de caracteres Unicode se llama Cadena. En Elm, las cadenas se escriben entre "" comillas dobles . Una cadena es un fragmento de texto como se muestra a continuación.

> "TutorialsPoint"
"TutorialsPoint" : String
> location = "Hyderabad" --variable
"Hyderabad" : String
> location
"Hyderabad" : String
>

Funciones de cadena

Algunas funciones comunes que se pueden utilizar para consultar o manipular valores de cadena se indican a continuación. Utilice REPL para probar los ejemplos que se dan a continuación.

No Señor Método Descripción
1 isEmpty: String -> Bool verifica que la cadena esté vacía
2 reverso: Cadena -> Cadena invierte una cadena de entrada
3 longitud: String -> Int devuelve una longitud entera
4 añadir: Cadena -> Cadena -> Cadena agrega dos cadenas y devuelve una nueva cadena
5 añadir: String -> Sconcat: List String -> String agrega una lista de cadenas y devuelve una nueva cadena
6 split: String -> String -> List String divide una cadena de entrada usando un separador dado, devuelve una lista de cadenas
7 rebanada: Int -> Int -> Cadena -> Cadena devuelve una subcadena con un índice inicial, final y una cadena de entrada
8 contiene: Cadena -> Cadena -> Bool devuelve verdadero si la segunda cadena contiene la primera
9 toInt: String -> Result.Result String Int analiza una cadena a un entero
10 toInt: String -> Result.Result String Int analiza una cadena a un entero
11 toFloat: String -> Result.Result String Float analiza una cadena para flotar
12 fromChar: Char -> Cadena crea una cadena a partir de un carácter determinado.
13 toList: String -> List Char convierte la cadena en una lista de caracteres
14 fromList: List Char -> String convierte una lista de caracteres en una cadena
15 toUpper: String -> String convierte la cadena de entrada a mayúsculas
dieciséis recortar: Cadena -> Cadena elimina los espacios en blanco a ambos lados de una cuerda.
17 filtro: (Char -> Bool) -> Cadena -> Cadena filtra el conjunto de caracteres de la cadena de entrada
18 mapa: (Char -> Char) -> String -> String transforma cada carácter en una cadena de entrada

esta vacio

Esta función se puede utilizar para determinar si una cadena está vacía. Esta función devuelve True si la cadena proporcionada está vacía.

Sintaxis

String.isEmpty String_value

Para verificar la firma de la función, escriba lo siguiente en elm REPL:

> String.isEmpty
<function> : String -> Bool

La firma de la función muestra Bool como tipo de retorno y el tipo de entrada como String -

Ilustración

> String.isEmpty ""
True : Bool
> String.isEmpty "Tutorialspoint"
False : Bool
> location = "Hyderabad"
"Hyderabad" : String
> String.isEmpty location
False : Bool

contrarrestar

Esta función invierte una cadena.

Sintaxis

String.reverse String_value

Para verificar la firma de la función, escriba lo siguiente en elm REPL:

> String.reverse
<function> : String -> String

La firma de la función muestra String como tipo de retorno y el tipo de entrada como String -

Ilustración

> String.reverse "TutorialsPoint"
"tnioPslairotuT" : String

longitud

Esta función devuelve la longitud de una cadena.

Sintaxis

String.length String_value

Para verificar la firma de la función, escriba lo siguiente en elm REPL:

> String.length
<function-> : String -> Int

La firma de la función muestra Int como tipo de retorno y el tipo de entrada como String.

Ilustración

> String.length "Mohtashim"
9 : Int

adjuntar

Esta función devuelve una nueva cadena agregando dos cadenas.

Sintaxis

String.append String_value1 String_value2

Para verificar la firma de la función, escriba lo siguiente en elm REPL:

> String.append
<function-> : String -> String -> String

Firma de muestra dos parámetros de entrada de cadena y un parámetro de salida de cadena

Ilustración

> String.append "Tutorials" "Point"
TutorialsPoint : String

concat

Esta función devuelve una nueva cadena concatenando muchas cadenas en una.

Sintaxis

String.concat [String1,String2,String3]

Para verificar la firma de la función, escriba lo siguiente en elm REPL:

> String.concat
<function> : List String -> String

La firma de muestra un parámetro de entrada Lista de cadenas y un tipo de retorno de cadena

Ilustración

> String.concat ["Hello","Tutorials","Point"]
HelloTutorialsPoint : String

división

Esta función divide una cadena usando un separador dado.

Sintaxis

String.split string_seperator String_value

Para verificar la firma de la función, escriba lo siguiente en elm REPL:

> String.split
<function> : String -> String -> List String

Signature of muestra dos parámetros de cadena de entrada y la salida como una lista de tipo de cadena.

Ilustración

> String.split "," "Hello,Tutorials,Point"
["Hello","Tutorials","Point"] : List String

rebanada

Esta función devuelve una subcadena dado un índice inicial y final. Los índices negativos se toman comenzando desde el final de la lista. El valor del índice comienza desde cero.

Sintaxis

String.slice start_index end_index String_value

Para verificar la firma de la función, escriba lo siguiente en elm REPL:

> String.slice
<function> : Int -> Int -> String -> String

La firma de muestra tres parámetros de entrada y un tipo de retorno.

Ilustración

> String.slice 0 13 "TutorialsPoint"
"TutorialsPoin" : String

contiene

Esta función devuelve True si la segunda cadena contiene la primera.

Sintaxis

String.contains string1 string2

Para verificar la firma de la función, escriba lo siguiente en elm REPL:

> String.contains
<function> : String -> String -> Bool

Firma de muestra el tipo de retorno bool y dos parámetros de entrada

Ilustración

> String.contains "Point" "TutorialsPoint"
True : Bool

toInt

Esta función convierte una cadena en un int.

Sintaxis

String.toInt string_value

Para verificar la firma de la función, escriba lo siguiente en elm REPL:

> String.toInt
<function> : String -> Result.Result String Int

Como toInt puede devolver un error, el tipo de retorno es Result, que es String o Int.

Ilustración

> String.toInt "20"
Ok 20 : Result.Result String Int
> String.toInt "abc"
Err "could not convert string 'abc' to an Int" : Result.Result String Int

flotar

Esta función convierte una cadena en un flotante.

Sintaxis

String.toFloat string_value

Para verificar la firma de la función, escriba lo siguiente en elm REPL:

> String.toFloat
<function> : String -> Result.Result String Float

Dado que toFloat puede devolver un error, el tipo de retorno es Result, que es String o Float.

Ilustración

> String.toFloat "20.50"
Ok 20.5 : Result.Result String Float
> String.toFloat "abc"
Err "could not convert string 'abc' to a Float" : Result.Result String Float

fromChar

Esta función crea una cadena a partir de un carácter determinado.

Sintaxis

String.fromChar character_value

Para verificar la firma del tipo de función siguiente en elm REPL:

> String.fromChar
<function> : Char -> String

La firma muestra String como tipo de retorno y la entrada como tipo Char

Ilustración

> String.fromChar 'c'
"c" : String

Listar

Esta función convierte una cadena en una lista de caracteres.

Sintaxis

String.toList string_value

Para verificar la firma de la función, escriba lo siguiente en elm REPL:

> String.toList
<function> : String -> List Char

La función de firmas muestra devuelve una lista de caracteres y toma una cadena de entrada.

Ilustración

> String.toList "tutorialspoint"
['t','u','t','o','r','i','a','l','s','p','o','i','n','t'] : List Char

fromList

Esta función convierte una lista de caracteres en una cadena.

Sintaxis

String.fromList list_of_characters

Para verificar la firma de la función, escriba lo siguiente en elm REPL:

> String.fromList
<function> : List Char -> String

La función de firmas muestra devuelve una lista de caracteres y toma una cadena de entrada.

Ilustración

> String.fromList ['h','e','l','l','o']
"hello" : String

toUpper

Esta función convierte una cadena en mayúsculas.

Sintaxis

String.toUpper String_value

Para verificar la firma de la función, escriba lo siguiente en elm REPL:

> String.toUpper
<function> : String -> String

Ilustración

> String.toUpper "hello"
"HELLO" : String

reducir

Esta función convierte una cadena a minúsculas.

Sintaxis

String.toLower String_value

Para verificar la firma de la función, escriba lo siguiente en elm REPL:

> String.toLower
<function> : String -> String

Ilustración

> String.toLower "AbCd"
"abcd" : String

podar

Esta función elimina los espacios en blanco a ambos lados de una cadena.

Sintaxis

String.trim String_value

Para verificar la firma de la función, escriba lo siguiente en elm REPL:

> String.trim
<function> : String -> String

Ilustración

> String.trim "tutorialspoint "
"tutorialspoint" : String

filtrar

Esta función filtra un conjunto de caracteres de la cadena de entrada. Conserve solo los personajes que pasen la prueba.

Sintaxis

String.filter test_function string_value

Para verificar la firma de la función, escriba lo siguiente en elm REPL:

> String.filter
<function> : (Char -> Bool) -> String -> String

La firma muestra que el filtro toma dos parámetros de entrada y devuelve una cadena. El primer parámetro es una función, que tiene la entrada Char y devuelve Bool.

Ilustración

En el ejemplo, estamos pasando Char.isUpper como parámetro al método de filtro; devuelve todos los caracteres en mayúsculas como se muestra a continuación.

> import Char
> String.filter Char.isUpper "abcDEF"
"DEF" : String

mapa

Esta función toma una cadena y transforma cada carácter en una cadena.

Sintaxis

String.filter mapping_function string_value

Para verificar la firma de la función, escriba lo siguiente en elm REPL:

> String.map
<function> : (Char -> Char) -> String -> String

Ilustración

El siguiente ejemplo reemplaza el carácter o por @ -

> String.map (\c -> if c == 'o' then '@' else c) "TutorialsPoint"
"Tut@rialsP@int" : String

Las estructuras de datos List, Tuples y Record se pueden utilizar para almacenar una colección de valores.

Este capítulo trata sobre cómo usar List en Elm.

Una lista es una colección de valores homogéneos. Los valores de una lista deben ser todos del mismo tipo de datos.

Tenga en cuenta las siguientes limitaciones al utilizar variables para almacenar valores:

  • Las variables son de naturaleza escalar. En otras palabras, en el momento de la declaración, una variable solo puede contener un valor. Esto significa que para almacenar n valores en un programa, se necesitarán n declaraciones de variables. Por tanto, el uso de variables no es factible cuando se necesita almacenar una colección mayor de valores.

  • A las variables de un programa se les asigna memoria en orden aleatorio, lo que dificulta la recuperación / lectura de los valores en el orden de su declaración.

Sintaxis

List_name = [value1,value2,value3.....valuen]

Ilustración

El siguiente ejemplo muestra cómo usar una lista en Elm. Pruebe este ejemplo en elm REPL:

> myList1 = [10,20,30]
[10,20,30] : List number
> myList2 = ["hello","world"]
["hello","world"] : List String

Si intentamos agregar valores de diferentes tipos en una lista, el compilador arrojará un error de falta de coincidencia de tipos. Esto se muestra a continuación.

> myList = [1,"hello"]
-- TYPE MISMATCH 
--------------------------------------------- 
repl-temp-000.elm

The 1st and 2nd entries in this list are different types of values.

4| [1,"hello"]
^^^^^^^
The 1st entry has this type:
   number
But the 2nd is:
   String

Operaciones de lista

La siguiente tabla muestra las operaciones comunes en una lista:

No Señor Método Descripción
1 isEmpty: Lista a -> Bool comprueba si la lista está vacía
2 reverso: Lista a -> Bool invierte la lista de entrada
3 longitud: Lista a -> Int devuelve el tamaño de la lista
4 máximo: Lista comparable -> Quizás. Quizás comparable devuelve el valor máximo
5 mínimo: Lista comparable -> Quizás. Quizás comparable devuelve el valor mínimo
6 suma: Número de lista -> número devuelve la suma de todos los elementos en la lista
7 producto: Número de lista -> número comprueba si la lista está vacía
8 sort: Lista comparable -> Lista comparable ordena la lista en orden ascendente
9 concat: Lista (Lista a) -> Lista a fusiona un montón de listas en una
10 añadir: Lista a -> Lista a -> Lista a fusiona dos listas juntas
11 rango: Int -> Int -> List Int devuelve una lista de números de principio a fin
12 filtro: (a -> Bool) -> Lista a -> Lista a filtra la lista de valores de la lista de entrada
13 cabeza: Lista a -> Quizás. devuelve el primer elemento de la lista
14 tail:: Lista a -> Quizás. Quizás (Lista a) devuelve todos los elementos excepto el encabezado

esta vacio

Esta función devuelve verdadero si una lista está vacía.

Sintaxis

List.isEmpty list_name

Para verificar la firma de la función, escriba lo siguiente en elm REPL:

> List.isEmpty
<function> : List a -> Bool

Ilustración

> List.isEmpty
<function> : List a -> Bool

> List.isEmpty [10,20,30]
False : Bool

contrarrestar

Esta función invierte la lista.

Sintaxis

List.reverse list_name

Para verificar la firma de la función, escriba lo siguiente en elm REPL:

> List.reverse
<function> : List a -> List a

Ilustración

> List.reverse [10,20,30]
[30,20,10] : List number

longitud

Esta función devuelve la longitud de una lista.

Sintaxis

List.length list_name

Para verificar la firma de la función, escriba lo siguiente en elm REPL:

> List.length
<function> : List a -> Int

Ilustración

> List.length [10,20,30]
3 : Int

máximo

Esta función devuelve el elemento máximo en una lista no vacía.

Sintaxis

List.maximum list_name

Para verificar la firma de la función, escriba lo siguiente en elm REPL:

> List.maximum
<function> : List comparable -> Maybe.Maybe comparable

Ilustración

> List.maximum [10,20,30]
Just 30 : Maybe.Maybe number
> List.maximum []
Nothing : Maybe.Maybe comparable

mínimo

Esta función devuelve el elemento mínimo en una lista no vacía.

Sintaxis

List.minimum list_name

Para verificar la firma de la función, escriba lo siguiente en elm REPL:

> List.minimum
<function> : List comparable -> Maybe.Maybe comparable

Ilustración

> List.minimum [10,20,30]
Just 10 : Maybe.Maybe number

suma

Esta función devuelve la suma de todos los elementos de una lista.

Sintaxis

List.sum list_name

Para verificar la firma de la función, escriba lo siguiente en elm REPL:

> List.sum
<function> : List number -> number

Ilustración

> List.sum [10,20,30]
60 : number

producto

Esta función devuelve el producto de todos los elementos de una lista.

Sintaxis

List.product list_name

Para verificar la firma de la función, escriba lo siguiente en elm REPL:

<function>  : List number ->  number

Ilustración

List.product [10,20,30]
6000 : number

ordenar

Esta función ordena los valores de menor a mayor en una lista.

Sintaxis

List.sort list_name

Para verificar la firma de la función, escriba lo siguiente en elm REPL:

> List.sort
<function> : List comparable -> List comparable

Ilustración

> List.sort [10,20,30]
[10,20,30] : List number

concat

Esta función concatena un montón de listas en una sola lista.

Sintaxis

List.concat [ [list_name1],[list_name2],[list_name3],.....[list_nameN] ]

Para verificar la firma de la función, escriba lo siguiente en elm REPL:

> List.concat
<function> : List (List a) -> List a

Ilustración

> List.concat [[10,20], [30,40],[50,60]]
[10,20,30,40,50,60] : List number

adjuntar

Esta función junta dos listas.

Sintaxis

List.append [list_name1] [list_name2]

Para verificar la firma de la función, escriba lo siguiente en elm REPL:

> List.append
<function> : List a -> List a -> List a

Ilustración

> List.append [10,20] [30,40]
[10,20,30,40] : List number

El operador ++ también se puede utilizar para agregar una lista a otra. Esto se muestra en el siguiente ejemplo:

> [10.1,20.2] ++ [30.3,40.4]
[10.1,20.2,30.3,40.4] : List Float

rango

Esta función crea una lista de números, cada elemento se incrementa en uno. El número más bajo y más alto que debería estar en la lista se pasa a la función.

Sintaxis

List.range start_range end_range

Para verificar la firma de la función, escriba lo siguiente en elm REPL:

> List.range
<function> : Int -> Int -> List Int

Ilustración

> List.range 1 10
[1,2,3,4,5,6,7,8,9,10] : List Int

filtrar

Esta función filtra un conjunto de valores de la lista de entrada. Conserve solo los valores que pasen la prueba.

Sintaxis

List.filter test_function input_list

Para verificar la firma de la función, escriba lo siguiente en elm REPL:

> List.filter
<function> : (a -> Bool) -> List a -> List a

Ilustración

El siguiente ejemplo filtra todos los números pares de una lista de entrada

> List.filter (\n -> n%2==0) [10,20,30,55]
[10,20,30] : List Int

cabeza

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

Sintaxis

List.head input_list

Para verificar la firma de la función, escriba lo siguiente en elm REPL:

> List.head
<function> : List a -> Maybe.Maybe a

Ilustración

> List.head [10,20,30,40]
Just 10 : Maybe.Maybe number
> List.head []
Nothing : Maybe.Maybe a

cola

Esta función devuelve todos los elementos después del primero en la lista.

Sintaxis

List.tail input_list

Para verificar la firma de la función, escriba lo siguiente en elm REPL:

> List.tail
<function> : List a -> Maybe.Maybe (List a)

Ilustración

> List.tail [10,20,30,40,50]
Just [20,30,40,50] : Maybe.Maybe (List number)
> List.tail [10]
Just [] : Maybe.Maybe (List number)
> List.tail []
Nothing : Maybe.Maybe (List a)

Uso del operador Contras

El operador contras (::) agrega un elemento al principio de una lista.

Ilustración

> 10::[20,30,40,50]
[10,20,30,40,50] : List number

El nuevo elemento que se agregará y el tipo de datos de los valores de la lista deben coincidir. El compilador arroja un error si los tipos de datos no coinciden.

> [1,2,3,4]::[5,6,7,8]
-- TYPE MISMATCH ---------------------------------
------------ repl-temp-000.elm

The right side of (::) is causing a type mismatch.

3| [1,2,3,4]::[5,6,7,8]
			  ^^^^^^^^^
(::) is expecting the right side to be a:

   List (List number)

But the right side is:

   List number
Hint: With operators like (::) I always check the left side first. If it seems fine, 
I assume it is correct and check the right side. So the 
problem may be in how the left and right arguments interact.

Las listas son inmutables

Comprobemos si las listas son inmutables en Elm. La primera lista myList cuando se concatena con el valor 1 crea una nueva lista y se devuelve a myListCopy . Por tanto, si mostramos la lista inicial, sus valores no cambiarán.

> myList = [10,20,30]
[10,20,30] : List number
> myListCopy = 1::myList
[1,10,20,30] : List number
> myList
[10,20,30] : List number
>myList == myListCopy
False : Bool

A veces, puede ser necesario almacenar una colección de valores de diversos tipos. Elm nos da una estructura de datos llamada tupla que sirve para este propósito.

Una tupla representa una colección heterogénea de valores. En otras palabras, las tuplas permiten almacenar múltiples campos de diferentes tipos. Una tupla almacena un número fijo de valores. Las tuplas son útiles cuando desea devolver múltiples valores de diferentes tipos de una función. Estas estructuras de datos son inmutables como otros tipos en elm.

Sintaxis

(data1,data2)

A continuación se muestra un ejemplo sencillo:

> ("TuotrialsPoint",5,True,"Hyderabad")
("TuotrialsPoint",5,True,"Hyderabad") : ( String, number, Bool, String )

En las secciones siguientes, aprenderemos sobre las diferentes operaciones de tupla.

primero

Esta operación extrae el primer valor de una tupla.

Sintaxis

Tuple.first tuple_name
> Tuple.first
<function> : ( a1, a2 ) -> a1

Ilustración

> Tuple.first (10,"hello")
10 : number

segundo

los second La operación de tupla extrae el segundo valor de una tupla.

Sintaxis

Tuple.second tuple_name
> Tuple.second
<function> : ( a1, a2 ) -> a2

Ilustración

> Tuple.second (10,"hello")
"hello" : String

Lista de tuplas

Una lista puede almacenar tuplas. Si se utilizan tuplas dentro de una lista, asegúrese de que todas sean del mismo tipo de datos y tengan el mismo número de parámetros.

Ilustración

> [("hello",20),("world",30)]
[("hello",20),("world",30)] : List ( String, number )

Tupla con función

Una función puede devolver tuplas. Además, las tuplas se pueden pasar como parámetros a funciones.

Ilustración 1

El siguiente ejemplo define una función fn_checkEven. Esta función acepta un valor entero como parámetro y devuelve una tupla.

> fn_checkEven no = \
   if no%2 == 0 then \
      (True,"The no is Even")\
   else \
      (False,"No is not even")
<function> : Int -> ( Bool, String )
> fn_checkEven 10
(True,"The no is Even") : ( Bool, String )
> fn_checkEven 11
(False,"No is not even") : ( Bool, String )
>

Ilustración 2

Lo siguiente pasa una tupla como parámetro a una función.

> fn_add (a,b) = \
| a+b
<function> : ( number, number ) -> number
> fn_add (10,20)
30 : number

La función fn_add toma una tupla con 2 valores numéricos y devuelve su suma.

Desestructuración

La desestructuración implica dividir una tupla en valores individuales. Para acceder a valores individuales en una tupla con tres o más elementos, usamos la desestructuración. Aquí, asignamos cada valor en una tupla a diferentes variables. Usando _ uno puede definir marcadores de posición para valores que serán ignorados u omitidos.

Ilustración

> (first,_,_) = (10,20,30)
10 : number
> first
10 : number

Ilustración

En este ejemplo, usaremos let..in block syntax para desestructurar. El bloque let contiene las variables y el bloque in contiene expresiones que se deben evaluar y el valor que se debe devolver.

> t1 = (10,20,30)
(10,20,30) : ( number, number1, number2 )
> let \
(a,b,c) = t1 \
in\
a + b +c
60 : number

Estamos declarando las variables abc en la cláusula let y accediendo a ellas usando la cláusula in.

La estructura de datos de registro en Elm se puede utilizar para representar datos como pares clave-valor. Se puede utilizar un registro para organizar datos relacionados para permitir un fácil acceso y actualización de datos. Los registros Elm son similares a los objetos en JavaScript. Los elementos de datos de un registro se conocen como campos.

Definición de un registro

Utilice la siguiente sintaxis para definir un registro:

Sintaxis

record_name = {fieldname1 = value1, fieldname2 = value2....fieldnameN = valueN}

Un registro puede almacenar datos de varios tipos. Los nombres de campo en un registro deben cumplir con las reglas generales para nombrar un identificador de Elm.

Accediendo a valores de registro

Utilice la siguiente sintaxis para acceder a campos individuales en un registro.

Sintaxis

record_name.fieldname

O

.fieldname record_name

Ilustración

Pruebe lo siguiente en Elm REPL:

> company = {name="TutorialsPoint",rating=4.5}
{ name = "TutorialsPoint", rating = 4.5 } : { name : String, rating : Float }
> company.name
"TutorialsPoint" : String
> .rating company
4.5 : Float

Uso de Record with List

Un registro se puede almacenar dentro de una lista. Todos los valores de campo del registro deben ser del mismo tipo.

Sintaxis

list_name = [ {field_name1 = value1},{field_name1 = value2}]

O

list_name = [record_name1, record_name2, record_name3....record_nameN]

Ilustración

Pruebe lo siguiente en Elm REPL:

> [{name = "Mohtashim"},{name = "kannan"}]
[{ name = "Mohtashim" },{ name = "kannan" }] : List { name : String }
> record1 = {name = "FirstRecord"}
{ name = "FirstRecord" } : { name : String }
> record2 = {name = "SecondRecord"}
{ name = "SecondRecord" } : { name : String }
> recordList = [record1,record2]
[{ name = "FirstRecord" },{ name = "SecondRecord" }] : List { name : String }

Actualizar un registro

Los registros son inmutables en Elm. Cuando se actualiza un registro, se devuelve un nuevo registro con valores actualizados. El campo puede contener un valor de un tipo diferente al actualizar un registro.

Sintaxis

{record_name | field_name1 = new_value1, field_name2 = new_value2,field_name3 = new_value3....field_nameN = new_valueN}

Ilustración

Pruebe lo siguiente en Elm REPL:

> record1 = {name="FirstRecord"}
{ name = "FirstRecord" } : { name : String }
> record1_updated = {record1 | name = "FirstRecordUpdate"}
{ name = "FirstRecordUpdate" } : { name : String }
> record1
{ name = "FirstRecord" } : { name : String }
> record1 == record1_updated
False : Bool

Ilustración

El siguiente ejemplo actualiza varios campos de un registro. Pruebe lo siguiente en Elm REPL:

> record3 = {a = 1,b = 2,c = 3,d = 4,e = 5}
{ a = 1, b = 2, c = 3, d = 4, e = 5 }
: { a : number, b : number1, c : number2, d : number3, e : number4 }
> record4 = {record3 | d=400 ,e=500}
{ a = 1, b = 2, c = 3, d = 400, e = 500 }
: { a : number2, b : number3, c : number4, d : number, e : number1 }
>

Alias ​​de tipos

El alias de tipo define un esquema para un registro. En otras palabras, un alias de tipo define qué campos puede almacenar el registro y el tipo de valor que pueden almacenar estos campos. Por lo tanto, el programador no se equivocará al perder algún atributo específico al asignar valores.

Sintaxis

type alias alias_name = {field_name1:data_type,field_name2:data_type,....field_nameN:data_type}

Ilustración

Ejecute lo siguiente en Elm REPL:

> type alias Developer = { name:String,location:String,age:Int}
> dev1 = Developer "kannan" "Mumbai" 20
{ name = "kannan", location = "Mumbai", age = 20 } : Repl.Developer
> dev2 = Developer "mohtashim" "hyderabad" 20
{ name = "mohtashim", location = "hyderabad", age = 20 } : Repl.Developer
>

Ahora, si olvida escribir ubicación y edad, la declaración devuelve una función, que tiene parámetros de entrada para los campos de ubicación y edad.

> dev3 = Developer "Bhagavati"
<function> : String -> Int -> Repl.Developer
We can invoke the function as shown below and pass to it the values for location and age fields.
> dev3 "Pune" 25
{ name = "Bhagavati", location = "Pune", age = 25 } : Repl.Developer

Un error es cualquier condición inesperada en un programa. Los errores pueden ocurrir en tiempo de compilación o en tiempo de ejecución. Los errores de tiempo de compilación ocurren durante la compilación de un programa (por ejemplo, un error en la sintaxis del programa) mientras que los errores de tiempo de ejecución ocurren durante la ejecución del programa. A diferencia de otros lenguajes de programación, Elm no arroja errores en tiempo de ejecución.

Considere una aplicación que acepta la edad de un usuario. La aplicación debería arrojar un error si la edad es cero o negativa. En este caso, la aplicación Elm puede usar el concepto de manejo de errores para generar explícitamente un error en tiempo de ejecución si el usuario ingresa cero o un valor negativo como edad. El manejo de errores especifica el curso de acción si ocurre algo inesperado durante la ejecución del programa.

El lenguaje de programación Elm maneja los errores de las siguientes maneras:

  • MayBe
  • Result

Tal vez

Considere la función de búsqueda en una aplicación. La función de búsqueda devuelve datos relacionados si se encuentra la palabra clave de búsqueda; de lo contrario, no devuelve nada. Este caso de uso se puede implementar en Elm usando el tipo MayBe.

Sintaxis

variable_name:MayBe data_type

Una variable de tipo MayBe puede contener cualquiera de los siguientes valores:

  • Just some_Value: se utiliza si hay datos válidos.

  • Nada: se utiliza si el valor está ausente o se desconoce. Nada es equivalente a nulo en otros lenguajes de programación.

Ilustración

El siguiente ejemplo muestra cómo utilizar el tipo MayBe con variables y función.

Step 1 - Crea un MayBeDemo.elm archivo y agregue el siguiente código

-- MayBeDemo.elm
module MayBeDemo exposing(..)
import Maybe

--declaring a MayBe variable and assigning value to it
userName : Maybe String
userName = Just "Mohtashim"

--declaring a MayBe variable and assigning value to it
userAge :Maybe Int
userAge = Just 20

--declaring a MayBe variable and assigning value to it
userSalary:Maybe Float
userSalary = Nothing

--declaring a custom type
type Country = India | China | SriLanka

--defining a function that takes a String parameter as input and returns a value of type MayBe

getCountryFromString : String -> Maybe Country
getCountryFromString p =
case p of
   "India"
      -> Just India
   "China"
      -> Just China
   "SriLanka"
      -> Just SriLanka
   _
      -> Nothing

Step 2 - Importe el módulo en elm repl y ejecútelo como se indica a continuación

E:\ElmWorks\ErroApp> elm repl
---- elm-repl 0.18.0 -----------------------------------------------------------
:help for help, :exit to exit, more at 
      
        -------------------------------------------------------------------------------- > import MayBeDemo exposing(..) > userName Just "Mohtashim" : Maybe.Maybe String > userAge Just 20 : Maybe.Maybe Int > userSalary Nothing : Maybe.Maybe Float > getCountryFromString "India" Just India : Maybe.Maybe MayBeDemo.Country > getCountryFromString "india" Nothing : Maybe.Maybe MayBeDemo.Country 
      

La función comprueba si el valor pasado a la función es India, China o SriLanka. Si el valor del parámetro no coincide con ninguno de estos, no devuelve nada.

Resultado

Considere un ejemplo, donde la aplicación necesita validar alguna condición y generar un error si la condición no se cumple. El tipo de resultado se puede utilizar para lograr esto. El tipo de resultado debe usarse si la aplicación desea generar explícitamente un error y devolver detalles sobre lo que salió mal.

Sintaxis

La declaración del tipo de resultado toma dos parámetros: el tipo de datos del error (generalmente String) y el tipo de datos del resultado que se devolverá si todo va bien.

type Result error_type data_value_type
= Ok data_value
| Err error_message

El tipo de resultado devuelve cualquiera de los siguientes valores:

  • Ok some_value: representa el resultado que se devolverá

  • Err: representa el mensaje de error que se devolverá si no se cumplen las condiciones esperadas.

Ilustración 1

Pruebe el siguiente ejemplo en Elm REPL:

> String.toInt
<function> : String -> Result.Result String Int
-- successful result
> String.toInt "10"
Ok 10 : Result.Result String Int
-- unsuccessful result , Error
> String.toInt "a"
Err "could not convert string 'a' to an Int" : Result.Result String Int

La función String.toInt devuelve un valor entero si el parámetro pasado es válido. Si el parámetro no es un número, la función devuelve un error.

Ilustración 2

El siguiente ejemplo acepta la edad como parámetro. La función devuelve la edad si está entre 0 y 135; de lo contrario, devuelve un mensaje de error apropiado.

Step 1 - Cree un archivo ResultDemo.elm y agréguele el siguiente código.

--ResultDemo.elm
module ResultDemo exposing(..)

userId : Result String Int
userId = Ok 10

emailId : Result String Int
emailId = Err "Not valid emailId"

isReasonableAge : String -> Result String Int
isReasonableAge input =
   case String.toInt input of
      Err r ->
         Err "That is not a age!"

   Ok age ->
      if age < 0 then
         Err "Please try again ,age can't be negative"
      else if age > 135 then
         Err "Please try agian,age can't be this big.."

   else
      Ok age

Step 2 - Importe el módulo en el paquete elm y ejecútelo como se indica a continuación

E:\ElmWorks\ElmRepo\15_ErrorHandling\15_Code> elm repl
---- elm-repl 0.18.0 -----------------------------------------------------------
:help for help, :exit to exit, more at <https://github.com/elm-lang/elm-repl>
--------------------------------------------------------------------------------
> import ResultDemo exposing (..)
> userId
Ok 10 : Result.Result String Int
> emailId
Err "Not valid emailId" : Result.Result String Int
> isReasonableAge "10"
Ok 10 : Result.Result String Int
> isReasonableAge "abc"
Err "That is not a age!" : Result.Result String Int

En este capítulo, discutiremos la forma estándar de crear aplicaciones en la plataforma Elm. Elm utiliza un patrón arquitectónico similar al patrón Modelo-Vista-Controlador.

A continuación se muestran las cuatro partes principales de Elm Architecture.

  • Model
  • View
  • Message
  • Update

¿Cómo funciona la arquitectura de Elm?

los modelcontiene el estado de la aplicación. Por ejemplo, si una aplicación muestra una lista de clientes, el estado contendrá los datos de cada cliente. Para mostrar el estado de una manera presentable, unview/ html debe ser generado. Una vez que el usuario interactúa con la vista presionando un botón o escribiendo datos en un formulario, la vista genera señales llamadasmessages. Los mensajes se pasan alupdatemétodo, que evalúa los mensajes y toma las medidas adecuadas. Por lo tanto, el método de actualización generará un nuevo modelo.

El nuevo modelo genera una nueva vista. La vista dará lugar a nuevas interacciones del usuario para señalar mensajes, que pasa a la función de actualización. Además, la función crea un nuevo modelo. Entonces, el ciclo se repite como se muestra en el diagrama anterior.

Modelo

El modelo se ocupa del estado de la aplicación. La sintaxis para definir un modelo se da a continuación:

-- Model syntax

type alias Model = {
   property1:datatype,
   proptery2:datatype
...
}

Para crear un modelo, primero debemos crear una plantilla con todas las propiedades requeridas. Cada propiedad especifica el estado de la aplicación.

Ver

La vista es una representación visual del estado de la aplicación. La vista sabe cómo tomar datos y generar páginas web a partir de ellos. Cuando un usuario interactúa con la Vista, el usuario puede manipular el estado generando mensajes. La sintaxis para definir una vista se da a continuación:

--View Syntax
view model =some_implementation

Mensaje

El mensaje es una solicitud del usuario para modificar el estado de la aplicación. Los mensajes se pasan como parámetro a la función de actualización.

--Message Syntax
type Message = Message1 |Message2 ...

La sintaxis muestra un tipo Mensaje. La aplicación elm editará el estado según los mensajes que se le envíen. Estas decisiones se toman en el método de actualización.

Actualizar

La función de actualización interpreta los mensajes, que se le pasan como parámetro, y actualiza el modelo.

--Update Syntax
update Message_type model =
   some_implementation

La función de actualización toma Message y modelo como parámetros.

Un administrador de paquetes es una herramienta de línea de comandos que automatiza el proceso de instalación, actualización, configuración y eliminación de paquetes en su aplicación.

Al igual que JavaScript tiene un administrador de paquetes llamado npm, elm tiene un administrador de paquetes llamado elm-package .

El administrador de paquetes realiza las siguientes tres tareas:

  • Instala todas las dependencias que necesita una aplicación elm
  • Publica paquetes personalizados
  • Determina la versión de su paquete cuando está listo para publicar y actualizar.

Comandos de Elm Package Manager

La siguiente tabla enumera los diversos comandos del administrador de paquetes de Elm:

No Señor. Mando Sintaxis Descripción
1 Instalar en pc instalación del paquete elm Instala paquetes para usar localmente
2 publicar publicación del paquete elm Publica su paquete en el catálogo central
3 bache protuberancia del paquete de olmo Incrementa los números de versión según los cambios de API
4 diff diferencia de paquete de olmo Obtiene diferencias entre dos API

Para publicar su paquete, debe alojar el código fuente en GitHub y tener la versión debidamente etiquetada con una etiqueta git. La siguiente ilustración muestra cómo usar elm-package manager para extraer una dependencia externa.

Ilustración - Instalación del paquete svg

En este ejemplo, veremos cómo integrar Scalable Vector Graphics (SVG) en una aplicación elm.

Step 1 - Crea una carpeta elmSvgApp

Step 2 - Instale el paquete svg usando el siguiente comando -

elm-package install elm-lang/svg

Step 3- Instale Cree un archivo SvgDemo.elm y escriba el contenido que se indica a continuación. Importamos el módulo Svg para dibujar un rectángulo de dimensión 100x100 y rellenar el color rojo.

import Svg exposing (..)
import Svg.Attributes exposing (..)

main =
   svg
   [ width "120"
   , height "120"
   , viewBox "0 0 120 120"
   ]
   [ rect
      [ x "10"
      , y "10"
      , width "100"
      , height "100"
      , rx "15"
      , ry "15"
      ,fill "red"
      ]
      []
   ]

Step 4- Ahora cree el proyecto usando elm make. \ SvgDemo.elm. Esto generará un index.html como se muestra a continuación:

El mensaje es un componente de la arquitectura Elm. Estos componentes son generados por la Vista en respuesta a la interacción del usuario con la interfaz de la aplicación. Los mensajes representan solicitudes de usuarios para alterar el estado de la aplicación.

Sintaxis

--Message Syntax
type Message = some_message1 |some_message2 ...|some_messageN

ilustracion

El siguiente ejemplo es una aplicación de contador simple. La aplicación incrementa y reduce el valor de una variable en 1 cuando el usuario hace clic en los botones Agregar y Restar respectivamente.

La aplicación tendrá 4 componentes. Los componentes se describen a continuación:

Mensaje

Los mensajes de este ejemplo serán:

type Message = Add | Subtract

Modelo

El modelo representa el estado de la aplicación. En la aplicación de contador, la definición del modelo se da a continuación; el estado inicial del contador será cero.

model = 0

Ver

La vista representa los elementos visuales de la aplicación. La vista contiene dos botones (+) y (-). Los mensajes Agregar y Restar son generados por la Vista cuando el usuario hace clic en los botones + y - respectivamente. A continuación, la Vista muestra el valor modificado del modelo.

view model =
-- invoke text function
h1[]
[   div[] [text "CounterApp from TutorialsPoint" ]
   ,button[onClick Subtract] [text "-"]
   ,div[][text (toString model)]
   ,button[onClick Add] [text "+"]
]

Actualizar

Este componente contiene código que debe ejecutarse para cada mensaje generado por la vista. Esto se muestra en el siguiente ejemplo:

update msg model =
case msg of
Add -> model+1
Subtract -> model-1

Poniendolo todo junto

Step 1- Crea una carpeta MessagesApp y archivo MessagesDemo.elm

Step 2 - Agregue el siguiente código en el archivo elm -

import Html exposing (..)
import Html.Events exposing(onClick)

model = 0 -- Defining the Model

--Defining the View

view model =
   h1[]
   [  div[] [text "CounterApp from TutorialsPoint" ]
      ,button[onClick Subtract] [text "-"]
      ,div[][text (toString model)]
      ,button[onClick Add] [text "+"]
   ]

--Defining the Messages

type Message = Add | Subtract

--Defining Update

update msg model =
case msg of
   Add -> model+1
   Subtract -> model-1

-- Define the main method
main =
   beginnerProgram
   {
      model=model
      ,view=view
      ,update=update
   }

Step 3 - Ejecuta el elm make commanden terminal. loselm make command compila el código y genera un archivo HTML a partir del archivo .elm creado anteriormente.

C:\Users\dell\elm\MessagesApp> elm make .\MessageDemo.elm
Some new packages are needed. Here is the upgrade plan.

   Install:
      elm-lang/core 5.1.1
      elm-lang/html 2.0.0
      elm-lang/virtual-dom 2.0.4

Do you approve of this plan? [Y/n] y
Starting downloads...

   ΓùÅ elm-lang/html 2.0.0
   ΓùÅ elm-lang/virtual-dom 2.0.4

ΓùÅ elm-lang/core 5.1.1
Packages configured successfully!
Success! Compiled 38 modules.
Successfully generated index.html

Step 4 - Abra el index.html y verifique el funcionamiento como se muestra a continuación -

Elm - Comandos

En los capítulos anteriores, discutimos los diversos componentes de la arquitectura Elm y sus funciones. El usuario y la aplicación se comunican entre sí mediante Mensajes.

Considere un ejemplo, donde la aplicación necesita comunicarse con otros componentes como un servidor externo, API, microservicio, etc. para atender la solicitud del usuario. Esto se puede lograr usando Comandos en Elm. Los mensajes y los comandos no son sinónimos. Los mensajes representan la comunicación entre un usuario final y la aplicación, mientras que los comandos representan cómo una aplicación de Elm se comunica con otras entidades. Se activa un comando en respuesta a un mensaje.

La siguiente figura muestra el flujo de trabajo de una aplicación Elm compleja:

El usuario interactúa con la vista. La vista genera un mensaje apropiado basado en la acción del usuario. El componente de actualización recibe este mensaje y activa un comando.

Sintaxis

La sintaxis para definir un comando es la siguiente:

type Cmd msg

El mensaje generado por la vista se pasa al comando.

Ilustración

El siguiente ejemplo realiza una solicitud a una API y muestra el resultado de la API.

La aplicación acepta un número del usuario y lo pasa a la API de Numbers. Esta API devuelve hechos relacionados con el número.

Los diversos componentes de la aplicación son los siguientes:

Módulo Http

El módulo Http de Elm se utiliza para crear y enviar solicitudes HTTP. Este módulo no forma parte del módulo principal. Usaremos el administrador de paquetes elm para instalar este paquete.

API

En este ejemplo, la aplicación se comunicará con la API de Numbers - "http://numbersapi.com/#42".

Ver

La vista de la aplicación contiene un cuadro de texto y un botón.

view : Model -> Html Msg
view model =
   div []
      [ h2 [] [text model.heading]
      ,input [onInput Input, value model.input] []
      , button [ onClick ShowFacts ] [ text "show facts" ]
      , br [] []
      , h3 [][text model.factText]
      ]

Modelo

El modelo representa el valor ingresado por el usuario y el resultado que será devuelto por la API.

type alias Model =
   { heading : String
   , factText : String
   , input :String
   }

Mensaje

La aplicación tiene los siguientes tres mensajes:

  • ShowFacts
  • Input
  • NewFactArrived

Al hacer clic en el botón Mostrar hechos , el mensaje ShowFacts se pasa al método de actualización. Cuando el usuario escribe algún valor en el cuadro de texto, el mensaje de entrada se pasa al método de actualización. Finalmente, cuando se reciba la respuesta del servidor Http, el mensaje NewFactArrived se pasará a actualizar.

type Msg
   = ShowFacts
   |Input String
   | NewFactArrived (Result Http.Error String)

Actualizar

El método de actualización devuelve una tupla, que contiene el modelo y los objetos de comando. Cuando el usuario hace clic en el botón Mostrar datos, el mensaje se pasa a la actualización que luego llama a NumbersAPI.

update : Msg -> Model -> (Model, Cmd Msg)
update msg model =
   case msg of
      Input newInput ->
      (Model "NumbersApi typing.." "" newInput ,Cmd.none)
      ShowFacts ->
         (model, getRadmonNumberFromAPI model.input)

      NewFactArrived (Ok newFact) ->
         (Model "DataArrived" newFact "", Cmd.none)

      NewFactArrived (Err _) ->
      (model, Cmd.none)

Función auxiliar

La función auxiliar getRandomNumberFromAPI invoca NumbersAPI y le pasa el número ingresado por el usuario. El resultado devuelto por la API se utiliza para actualizar el modelo.

getRadmonNumberFromAPI : String->Cmd Msg
getRadmonNumberFromAPI newNo =
   let
      url =
         "http://numbersapi.com/"++newNo
   in
      Http.send NewFactArrived (Http.getString url)
No Señor. Método Firma Descripción
1 Http.getString getString: String -> Request String Cree una solicitud GET e interprete el cuerpo de la respuesta como una cadena.
2 Http.send enviar: (Error de resultado a -> msg) -> Solicitar a -> Cmd msg Envíe una solicitud Http.

principal

Este es el punto de entrada del proyecto Elm.

main =
   Html.program
      { init = init
      , view = view
      , update = update
      , subscriptions = subscriptions
      }

Poniendolo todo junto

Step 1 - Cree la carpeta CommandApp y el archivo CommandDemo.elm.

Step 2- Instale el módulo http usando el comando elm package install elm-lang / http .

Step 2 - Escriba el contenido de CommandDemo.elm como se muestra a continuación -

import Html exposing (..)
import Html.Attributes exposing (..)
import Html.Events exposing (..)
import Http

main =
   Html.program
      { init = init
      , view = view
      , update = update
      , subscriptions = subscriptions
      }

-- MODEL
type alias Model =
   { heading : String
   , factText : String
   , input :String
   }

init : (Model, Cmd Msg)
init =
   ( Model "NumbersAPI" "NoFacts" "42"-- set model two fields
   , Cmd.none -- not to invoke api initially
   )

-- UPDATE

type Msg
   = ShowFacts
   |Input String
   | NewFactArrived (Result Http.Error String)

update : Msg -> Model -> (Model, Cmd Msg)
update msg model =
   case msg of
      Input newInput ->
      (Model "NumbersApi typing.." "" newInput ,Cmd.none)
      ShowFacts ->
         (model, getRadmonNumberFromAPI model.input)

      NewFactArrived (Ok newFact) ->
         (Model "DataArrived" newFact "", Cmd.none)

      NewFactArrived (Err _) ->
         (model, Cmd.none)

- VIEW

view : Model -> Html Msg
view model =
   div []
      [ h2 [] [text model.heading]
      ,input [onInput Input, value model.input] []
      , button [ onClick ShowFacts ] [ text "show facts" ]
      , br [] []
      , h3 [][text model.factText]
      ]

-- SUBSCRIPTIONS

subscriptions : Model -> Sub Msg
subscriptions model =
   Sub.none

-- HTTP

getRadmonNumberFromAPI : String->Cmd Msg
getRadmonNumberFromAPI newNo =
   let
      url =
      "http://numbersapi.com/"++newNo
   in
      Http.send NewFactArrived (Http.getString url)

Step 4 - Dispara el comando.

C:\Users\dell\elm\CommandApp> elm make .\CommandDemo.elm

Esto generará el archivo html como se muestra a continuación.

Elm - Suscripciones

En el capítulo anterior, discutimos que una Vista interactúa con otros componentes usando Comandos. Del mismo modo, un componente (por ejemplo, WebSocket) puede comunicarse con una vista mediante suscripciones. Las suscripciones son una forma en que una aplicación Elm puede recibir entradas externas como eventos de teclado, eventos de temporizador y eventos de WebSocket.

La siguiente figura explica la función de las suscripciones en una aplicación de Elm. El usuario interactúa con una aplicación de Elm a través de mensajes. La aplicación dada usa WebSocket y tiene dos modos de operación:

  • Enviar datos del lado del cliente al servidor de socket a través de Command
  • Reciba datos en cualquier momento desde el servidor de socket mediante suscripción

Sintaxis

La sintaxis para definir una suscripción se da a continuación:

type Sub msg

Ilustración

Entendamos las suscripciones con un ejemplo sencillo.

En el ejemplo que se muestra a continuación, la aplicación envía un mensaje al servidor. El servidor es un servidor de eco, que responde al cliente con el mismo mensaje. Todos los mensajes entrantes se muestran más tarde en una lista. Usaremos WebSocket (protocolo wss) para poder escuchar continuamente los mensajes del servidor. WebSocket enviará la entrada del usuario al servidor mediante comandos, mientras que utilizará la suscripción para recibir mensajes del servidor.

Los diversos componentes de la aplicación se dan a continuación:

Servidor de eco

Se puede acceder al servidor de eco utilizando el protocolo wss. El servidor de eco devuelve la entrada del usuario a la aplicación. El código para definir un servidor de eco se proporciona a continuación:

echoServer : String
echoServer =
"wss://echo.websocket.org"

Modelo

El modelo representa la entrada del usuario y una lista de mensajes entrantes del servidor de socket. El código para definir el modelo es el siguiente:

type alias Model =
   { input : String
   , messages : List String
   }

Mensajes

El tipo de mensaje contendrá Entrada para recibir entrada de texto del usuario. El mensaje Enviar se generará cuando el usuario haga clic en el botón para enviar el mensaje al servidor WebSocket. El NewMessage se utiliza cuando llega un mensaje del servidor de eco.

type Msg
   = Input String
   | Send
   | NewMessage String

Ver

La vista de la aplicación contiene un cuadro de texto y un botón de envío para enviar la entrada del usuario al servidor. La respuesta del servidor se muestra en la Vista usando una etiqueta div .

view : Model -> Html Msg
view model =
   div []
      [ input [onInput Input, value model.input] []
      , button [onClick Send] [text "Send"]
      , div [] (List.map viewMessage (List.reverse model.messages))
      ]

viewMessage : String -> Html msg
viewMessage msg =
   div [] [ text msg ]

Actualizar

La función de actualización toma el mensaje y los componentes del modelo. Actualiza el modelo según el tipo de mensaje.

update : Msg -> Model -> (Model, Cmd Msg)
update msg {input, messages} =
   case msg of
      Input newInput ->
         (Model newInput messages, Cmd.none)

   Send ->
      (Model "" messages, WebSocket.send echoServer input)

   NewMessage str ->
      (Model input (str :: messages), Cmd.none)
No Señor. Método Firma Descripción
1 WebSocket.listen escuchar: Cadena -> (Cadena -> msg) -> Sub msg Se suscribe a cualquier mensaje entrante en un websocket.
2 WebSocket.send enviar: Cadena -> Cadena -> Cmd msg Envía una solicitud wss a una dirección de servidor. Es importante que también estés suscrito a esta dirección con listen. Si no es así, se creará el conector web para enviar un mensaje y luego se cerrará.

Suscripción

La función de suscripción incluye el objeto modelo. Para recibir los mensajes del servidor WebSocket, llamamos WebSocket.listen pasando el mensaje como NewMessage . Cuando llega un mensaje nuevo del servidor, se llama al método de actualización.

subscriptions : Model -> Sub Msg
subscriptions model =
WebSocket.listen echoServer NewMessage

principal

La función principal es el punto de entrada a la aplicación elm como se muestra a continuación.

main =
   Html.program
      { init = init
      , view = view
      , update = update
      , subscriptions = subscriptions
      }

Poniendolo todo junto

Step 1 - Cree un directorio, SubscriptionApp y agregue un archivo, SubscriptionDemo.elm.

Step 2 - Agregue el siguiente contenido al archivo SubscriptionDemo.elm -

import Html exposing (..)
import Html.Attributes exposing (..)
import Html.Events exposing (..)
import WebSocket

main =
   Html.program
      { init = init
      , view = view
      , update = update
      , subscriptions = subscriptions
      }

echoServer : String
echoServer =
   "wss://echo.websocket.org"

-- MODEL

type alias Model =
   { input : String
   , messages : List String
   }

init : (Model, Cmd Msg)
init =
   (Model "" [], Cmd.none)

-- UPDATE
type Msg
   = Input String
   | Send
   | NewMessage String

update : Msg -> Model -> (Model, Cmd Msg)
update msg {input, messages} =
   case msg of
      Input newInput ->
      (Model newInput messages, Cmd.none)

   Send ->
      (Model "" messages, WebSocket.send echoServer input)

   NewMessage str ->
      (Model input (str :: messages), Cmd.none)

-- SUBSCRIPTIONS
subscriptions : Model -> Sub Msg
subscriptions model =
   WebSocket.listen echoServer NewMessage

-- VIEW
view : Model -> Html Msg
view model =
   div []
      [ input [onInput Input, value model.input] []
      , button [onClick Send] [text "Send"]
      , div [] (List.map viewMessage (List.reverse model.messages))
      ]

viewMessage : String -> Html msg
viewMessage msg =
div [] [ text msg ]

Step 3 - Instale el paquete websockets usando elm package manager.

C:\Users\dell\elm\SubscriptionApp> elm-package install elm-lang/websocket

Step 4 - Construya y genere el archivo index.html como se muestra a continuación.

C:\Users\dell\elm\SubscriptionApp> elm make .\SubscriptionDemo.elm

Step 5 - Tras la ejecución, se generará la siguiente salida -