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
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 en Linux
La guía de instalación específica de Linux de Visual Studio Code se puede encontrar en
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 -