Elm Language
Funktionen und Teilanwendung
Suche…
Syntax
- - Das Definieren einer Funktion ohne Argumente sieht genauso aus wie das Definieren eines Werts
Sprache = "Elm" - - Aufruf einer Funktion ohne Argumente durch Angabe ihres Namens
Sprache - - Parameter werden durch Leerzeichen getrennt und folgen dem Namen der Funktion
addiere xy = x + y - - eine Funktion auf die gleiche Weise aufrufen
addiere 5 2 - - eine Funktion teilweise anwenden, indem nur einige ihrer Parameter angegeben werden
Inkrement = 1 addieren - - Verwenden Sie den Operator |>, um den Ausdruck links an die Funktion rechts zu übergeben
zehn = 9 |> Schrittweite - - das <| Der Operator übergibt den Ausdruck rechts an die Funktion links
inkrementieren <| addiere 5 4 - - Verketten Sie zwei Funktionen zusammen mit dem Operator >>
backwardsYell = String.reverse >> String.toUpper - - Das << funktioniert in umgekehrter Richtung
backwardsYell = String.toUpper << String.reverse - - Eine Funktion mit einem nicht alphanumerischen Namen in Klammern erstellt einen neuen Operator
(#) xy = x * y
zehn = 5 # 2 - - Jeder Infix-Operator wird zu einer normalen Funktion, wenn Sie ihn in Klammern einschließen
zehn = (+) 5 5 - - optionale Typanmerkungen erscheinen über Funktionsdeklarationen
isTen: Int -> Bool
isTen n = wenn n == 10 dann wahr sonst falsch
Überblick
Die Funktionsanwendungssyntax in Elm verwendet keine Klammern oder Kommas und ist stattdessen Whitespace-sensitiv.
Um eine Funktion zu definieren, geben Sie ihren Namen multiplyByTwo und die Argumente x . Operationen nach Gleichheitszeichen = von einer Funktion zurückgegeben.
multiplyByTwo x =
x * 2
Um eine Funktion aufzurufen, geben Sie ihren Namen und ihre Argumente an:
multiplyByTwo 2 -- 4
Beachten Sie, dass eine Syntax wie multiplyByTwo(2) nicht erforderlich ist (auch wenn der Compiler sich nicht beschwert). Die Klammern dienen nur dazu, Vorrang aufzulösen:
> 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
Lambda-Ausdrücke
Elm hat eine spezielle Syntax für Lambda-Ausdrücke oder anonyme Funktionen:
\arguments -> returnedValue
Zum Beispiel in List.filter :
> List.filter (\num -> num > 1) [1,2,3]
[2,3] : List number
In der Tiefe wird der Beginn eines Lambda-Ausdrucks mit einem umgekehrten Schrägstrich \ markiert und mit dem Pfeil -> werden Argumente vom Funktionsrumpf getrennt. Wenn es mehr Argumente gibt, werden diese durch ein Leerzeichen getrennt:
normalFunction x y = x + y
-- is equivalent to
lambdaFunction = \x y -> x + y
> normalFunction 1 2
3 : number
> lambdaFunction 1 2
3 : number
Lokale Variablen
Es ist möglich, lokale Variablen innerhalb einer Funktion zu definieren
- Codewiederholung reduzieren
- benennen Sie die Unterausdrücke
- reduzieren Sie die Anzahl der übergebenen Argumente.
Das Konstrukt dafür ist 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!
Die Reihenfolge der Definitionen im ersten Teil von let spielt keine Rolle!
outOfOrder =
let
x =
y + 1 -- the compiler can handle this
y =
100
in
x + y
> outOfOrder
201 : number
Teilanwendung
Teilanwendung bedeutet das Aufrufen einer Funktion mit weniger Argumenten als dem Speichern und das Speichern des Ergebnisses als eine andere Funktion (die auf den Rest der Argumente wartet).
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
Als akademische Nebenbei bemerkt, Elm kann dies tun , weil der currying hinter den Kulissen.
Strenge und verspätete Bewertung
In elm wird der Wert einer Funktion berechnet, wenn das letzte Argument angewendet wird. Im folgenden Beispiel wird die Diagnose aus dem log gedruckt, wenn f mit 3 Argumenten aufgerufen wird oder eine aktuelle Form von f mit dem letzten Argument angewendet wird.
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
Manchmal möchten Sie verhindern, dass eine Funktion sofort angewendet wird. Eine typische Anwendung in elm ist Lazy.lazy die eine Abstraktion zur Steuerung der Anwendung von Funktionen bereitstellt.
lazy : (() -> a) -> Lazy a
Lazy Berechnungen haben eine Funktion von einem () oder Unit Typ-Argument. Der Einheitentyp ist üblicherweise der Typ eines Platzhalterarguments. In einer Argumentliste wird das entsprechende Argument als _ angegeben, um _ , dass der Wert nicht verwendet wird. Der Einheitswert in elm wird durch das spezielle Symbol () das konzeptionell ein leeres Tupel oder ein Loch darstellen kann. Es ähnelt der Liste der leeren Argumente in C, Javascript und anderen Sprachen, die Klammern für Funktionsaufrufe verwenden. Dies ist jedoch ein normaler Wert.
In unserem Beispiel kann f vor einer sofortigen Bewertung mit einem Lambda geschützt werden:
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
Die Funktionsauswertung wird immer dann verzögert, wenn eine Funktion teilweise angewendet wird.
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 hat eine always Funktion, mit der die Auswertung nicht verzögert werden kann. Da Ulme wertet alle Funktionsargumente unabhängig davon , ob , und wenn das Ergebnis der Funktionsanwendung verwendet wird, in eine Funktionsanwendung Umwickeln always nicht zu einer Verzögerung führen, da f vollständig als Parameter angewandt wird , um always .
alwaysF = always (f "a" "b" "c") -- <function> : a -> String
-- Diagnostic: ["a","b","c"] -- Evaluation wasn't delayed.
Infix-Operatoren und Infix-Notation
Elm ermöglicht die Definition von benutzerdefinierten Infix-Operatoren.
Infix-Operatoren werden in Klammern um den Namen einer Funktion definiert.
Betrachten Sie dieses Beispiel eines Infix-Operators für das Erstellen von Tupeln 1 => True -- (1, True) :
(=>) : a -> b -> ( a, b )
(=>) a b =
( a, b )
Die meisten Funktionen in Elm sind in Präfixnotation definiert.
Wenden Sie jede Funktion mithilfe der Infix-Notation an, indem Sie das erste Argument vor dem mit schweren Akzentzeichen versehenen Funktionsnamen angeben:
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]