Buscar..


Sintaxis

  • - Definir una función sin argumentos parece lo mismo que simplemente definir un valor
    language = "Elm"
  • - llamar a una función sin argumentos indicando su nombre
    idioma
  • - Los parámetros están separados por espacios y siguen el nombre de la función.
    agrega xy = x + y
  • - llamar a una función de la misma manera
    añadir 5 2
  • - aplicar parcialmente una función proporcionando solo algunos de sus parámetros
    incremento = agregar 1
  • - use el operador |> para pasar la expresión de la izquierda a la función de la derecha
    ten = 9 |> incremento
  • - el <| el operador pasa la expresión de la derecha a la función de la izquierda
    incremento <| añadir 5 4
  • - encadenar / componer dos funciones junto con el >> operador
    backwardsYell = String.reverse >> String.toUpper
  • - El << funciona igual en sentido inverso.
    backwardsYell = String.toUpper << String.reverse
  • - una función con un nombre no alfanumérico entre paréntesis crea un nuevo operador
    (#) xy = x * y
    diez = 5 # 2
  • - cualquier operador de infijo se convierte en una función normal cuando lo envuelve entre paréntesis
    diez = (+) 5 5
  • - Las anotaciones de tipo opcionales aparecen arriba de las declaraciones de funciones.
    isTen: Int -> Bool
    isTen n = if n == 10 entonces True más False

Visión general

La sintaxis de la aplicación de la función en Elm no usa paréntesis ni comas, y en su lugar es sensible al espacio en blanco.

Para definir una función, especifique su nombre multiplyByTwo y argumentos x , cualquier operación después del signo igual = es lo que se devuelve de una función.

multiplyByTwo x =
    x * 2

Para llamar a una función, especifique su nombre y argumentos:

multiplyByTwo 2  -- 4

Tenga en cuenta que la sintaxis como multiplyByTwo(2) no es necesaria (aunque el compilador no se queja). Los paréntesis solo sirven para resolver la precedencia:

> multiplyByTwo multiplyByTwo 2
-- error, thinks it's getting two arguments, but it only needs one

> multiplyByTwo (multiplyByTwo 2)
4 : number

> multiplyByTwo 2 + 2
6 : number
-- same as (multiplyByTwo 2) + 2

> multiplyByTwo (2 + 2)
8 : number

Expresiones lambda

Elm tiene una sintaxis especial para expresiones lambda o funciones anónimas:

\arguments -> returnedValue

Por ejemplo, como se ve en List.filter :

> List.filter (\num -> num > 1) [1,2,3]
[2,3] : List number

Más a la profundidad, se usa una barra invertida, \ , para marcar el comienzo de la expresión lambda, y la flecha, -> , se usa para delimitar argumentos del cuerpo de la función. Si hay más argumentos, se separan por un espacio:

normalFunction x y = x + y
-- is equivalent to
lambdaFunction = \x y -> x + y

> normalFunction 1 2
3 : number

> lambdaFunction 1 2
3 : number

Variables locales

Es posible definir variables locales dentro de una función para

  • reducir la repetición de código
  • dar nombre a subexpresiones
  • Reducir la cantidad de argumentos pasados.

El constructo para esto se let ... in ...

bigNumbers =
    let
        allNumbers =
            [1..100]

        isBig number =
            number > 95
    in
        List.filter isBig allNumbers

> bigNumbers
[96,97,98,99,100] : List number

> allNumbers
-- error, doesn't know what allNumbers is!

El orden de las definiciones en la primera parte de let no importa!

outOfOrder =
    let
        x =
            y + 1  -- the compiler can handle this

        y =
            100
    in
        x + y

> outOfOrder
201 : number

Solicitud parcial

La aplicación parcial significa llamar a una función con menos argumentos de los que tiene y guardar el resultado como otra función (que espera el resto de los argumentos).

multiplyBy: Int -> Int -> Int    
multiplyBy x y =
    x * y


multiplyByTwo : Int -> Int  -- one Int has disappeared! we now know what x is.
multiplyByTwo =
    multiplyBy 2


> multiplyByTwo 2
4 : Int

> multiplyByTwo 4
8 : Int

Como una nota de orientación académica, Elm puede hacer esto debido al curry detrás de escena.

Evaluación estricta y demorada.

En elm, el valor de una función se calcula cuando se aplica el último argumento. En el siguiente ejemplo, el diagnóstico desde el log se imprimirá cuando f se invoque con 3 argumentos o se aplique una forma currada de f con el último argumento.

import String
import Debug exposing (log)

f a b c = String.join "," (log "Diagnostic" [a,b,c]) -- <function> : String -> String -> String -> String

f2 = f "a1" "b2" -- <function> : String -> String

f "A" "B" "C"
-- Diagnostic: ["A","B","C"]
"A,B,C" : String

f2 "c3"
-- Diagnostic: ["a1","b2","c3"]
"a1,b2,c3" : String

A veces querrá evitar que una función se aplique de inmediato. Un uso típico en elm es Lazy.lazy que proporciona una abstracción para controlar cuándo se aplican las funciones.

lazy : (() -> a) -> Lazy a

Los cálculos perezosos toman una función de uno () o argumento de tipo de Unit . El tipo de unidad es convencionalmente el tipo de un argumento de marcador de posición. En una lista de argumentos, el argumento correspondiente se especifica como _ , lo que indica que el valor no se usa. El valor de la unidad en olmo se especifica mediante el símbolo especial () que puede representar conceptualmente una tupla vacía o un agujero. Se parece a la lista de argumentos vacía en C, Javascript y otros idiomas que usan paréntesis para llamadas a funciones, pero es un valor ordinario.

En nuestro ejemplo, f puede ser protegido para que no se evalúe inmediatamente con un lambda:

doit f = f () -- <function> : (() -> a) -> a
whatToDo = \_ -> f "a" "b" "c" -- <function> : a -> String
-- f is not evaluated yet

doit whatToDo
-- Diagnostic: ["a","b","c"]
"a,b,c" : String

La evaluación de la función se retrasa cada vez que una función se aplica parcialmente.

defer a f = \_ -> f a -- <function> : a -> (a -> b) -> c -> b

delayF = f "a" "b" |> defer "c" -- <function> : a -> String

doit delayF
-- Diagnostic: ["a","b","c"]
"a,b,c" : String

Elm tiene una función de always , que no puede usarse para retrasar la evaluación. Debido a que elm evalúa todos los argumentos de la función independientemente de si se usa el resultado de la aplicación de función y cuándo, el ajuste de una aplicación de función no always causará un retraso, porque f se aplica completamente como parámetro para always .

alwaysF = always (f "a" "b" "c") -- <function> : a -> String
-- Diagnostic: ["a","b","c"] -- Evaluation wasn't delayed.

Operadores de infijo y notación de infijo.

Elm permite la definición de operadores de infijo personalizados.

Los operadores de infijo se definen utilizando paréntesis alrededor del nombre de una función.

Considere este ejemplo de operador infijo para construcciones Tuples 1 => True -- (1, True) :

(=>) : a -> b -> ( a, b )
(=>) a b =
    ( a, b )

La mayoría de las funciones en Elm se definen en la notación de prefijo.

Aplique cualquier función utilizando la notación de infijo especificando el primer argumento antes del nombre de la función incluido con el carácter de acento grave:

import List exposing (append)


append [1,1,2] [3,5,8]   -- [1,1,2,3,5,8]
[1,1,2] `append` [3,5,8] -- [1,1,2,3,5,8]


Modified text is an extract of the original Stack Overflow Documentation
Licenciado bajo CC BY-SA 3.0
No afiliado a Stack Overflow