Elm Language
Fonctions et application partielle
Recherche…
Syntaxe
- - définir une fonction sans argument revient à définir simplement une valeur
language = "Elm" - - appeler une fonction sans argument en indiquant son nom
la langue - - les paramètres sont séparés par des espaces et suivent le nom de la fonction
ajouter xy = x + y - - appeler une fonction de la même manière
ajouter 5 2 - - appliquer partiellement une fonction en ne fournissant que certains de ses paramètres
incrémenter = ajouter 1 - - utilisez l’opérateur |> pour passer l’expression de gauche à la fonction de droite
dix = 9 |> incrément - - le <| l'opérateur passe l'expression à droite à la fonction de gauche
incrémenter <| ajouter 5 4 - - enchaîner / composer deux fonctions avec l'opérateur >>
backwardsYell = String.reverse >> String.toUpper - - le << fonctionne de la même manière en sens inverse
backwardsYell = String.toUpper << String.reverse - - une fonction avec un nom non alphanumérique entre parenthèses crée un nouvel opérateur
(#) xy = x * y
dix = 5 # 2 - - tout opérateur infixe devient une fonction normale lorsque vous l'enveloppez entre parenthèses
dix = (+) 5 5 - - Les annotations de type facultatives apparaissent au-dessus des déclarations de fonction
isTen: Int -> Bool
isTen n = si n == 10 alors vrai sinon faux
Vue d'ensemble
La syntaxe de l'application de fonction dans Elm n'utilise pas de parenthèse ni de virgule et est plutôt sensible aux espaces.
Pour définir une fonction, spécifiez son nom multiplyByTwo et les arguments x , toute opération après un signe égal = est ce qui a été renvoyé par une fonction.
multiplyByTwo x =
x * 2
Pour appeler une fonction, spécifiez son nom et ses arguments:
multiplyByTwo 2 -- 4
Notez que la syntaxe comme multiplyByTwo(2) n'est pas nécessaire (même si le compilateur ne se plaint pas). Les parenthèses servent uniquement à résoudre la priorité:
> 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
Expressions lambda
Elm a une syntaxe spéciale pour les expressions lambda ou les fonctions anonymes:
\arguments -> returnedValue
Par exemple, comme vu dans List.filter :
> List.filter (\num -> num > 1) [1,2,3]
[2,3] : List number
Plus loin à la profondeur, une barre oblique inversée, \ , est utilisée pour marquer le début de l'expression lambda, et la flèche, -> , permet de délimiter les arguments du corps de la fonction. S'il y a plus d'arguments, ils sont séparés par un espace:
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
Il est possible de définir des variables locales dans une fonction pour
- réduire la répétition du code
- donner un nom aux sous-expressions
- réduire la quantité d'arguments passés.
La construction de ceci est 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!
L'ordre des définitions dans la première partie de let n'a pas d'importance!
outOfOrder =
let
x =
y + 1 -- the compiler can handle this
y =
100
in
x + y
> outOfOrder
201 : number
Application partielle
Une application partielle consiste à appeler une fonction avec moins d'arguments et à enregistrer le résultat sous une autre fonction (qui attend le reste des arguments).
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
En tant que sidenote académique, Elm peut le faire en raison du curry derrière les coulisses.
Évaluation stricte et différée
Dans elm, la valeur d'une fonction est calculée lorsque le dernier argument est appliqué. Dans l'exemple ci-dessous, le diagnostic du log sera imprimé lorsque f est appelé avec 3 arguments ou qu'une forme curry de f est appliquée avec le dernier argument.
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
Parfois, vous voudrez empêcher une fonction d'être appliquée immédiatement. Une utilisation typique dans elm est Lazy.lazy qui fournit une abstraction pour contrôler quand les fonctions sont appliquées.
lazy : (() -> a) -> Lazy a
Les calculs paresseux prennent une fonction d'un argument de type () ou d' Unit . Le type d'unité est classiquement le type d'un argument d'espace réservé. Dans une liste d'arguments, l'argument correspondant est spécifié sous la forme _ , indiquant que la valeur n'est pas utilisée. La valeur unitaire dans elm est spécifiée par le symbole spécial () qui peut représenter conceptuellement un tuple vide ou un trou. Il ressemble à la liste d'arguments vide en C, Javascript et autres langages qui utilisent des parenthèses pour les appels de fonctions, mais c'est une valeur ordinaire.
Dans notre exemple, f peut être protégé contre une évaluation immédiate avec 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
L'évaluation de la fonction est retardée à chaque fois qu'une fonction est partiellement appliquée.
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 a une fonction always active, qui ne peut pas être utilisée pour retarder l'évaluation. Parce que l' orme évalue tous les arguments de la fonction , peu importe si et lorsque le résultat de l'application de fonction est utilisée, enroulant une application de fonction always ne causera pas un retard, parce que f est pleinement appliquée en tant que paramètre always .
alwaysF = always (f "a" "b" "c") -- <function> : a -> String
-- Diagnostic: ["a","b","c"] -- Evaluation wasn't delayed.
Opérateurs Infix et notation infixe
Elm permet la définition d'opérateurs d'infix personnalisés.
Les opérateurs Infix sont définis à l'aide de parenthèses autour du nom d'une fonction.
Considérons cet exemple d'opérateur infixe pour construction Tuples 1 => True -- (1, True) :
(=>) : a -> b -> ( a, b )
(=>) a b =
( a, b )
La plupart des fonctions dans Elm sont définies dans la notation de préfixe.
Appliquez une fonction en utilisant la notation infixe en spécifiant le premier argument avant le nom de la fonction entouré d'un caractère 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]