Sök…


Syntax

  • - Att definiera en funktion utan några argument ser ut som att helt enkelt definiera ett värde
    språk = "alm"
  • - ringa en funktion utan argument genom att ange dess namn
    språk
  • - parametrar separeras med mellanslag och följer funktionens namn
    lägg till xy = x + y
  • - ringa en funktion på samma sätt
    lägg till 5 2
  • - tillämpa en funktion delvis genom att endast tillhandahålla några av dess parametrar
    inkrement = lägg till 1
  • - använd |> -operatören för att skicka uttrycket till vänster till funktionen till höger
    tio = 9 |> steg
  • - <| operatören överför uttrycket till höger till funktionen till vänster
    steg <| lägg till 5 4
  • - kedja / komponera två funktioner tillsammans med >> operatören
    bakåtYell = String.reverse >> String.toUpper
  • - << fungerar på samma sätt i omvänd riktning
    bakåtYell = String.toUpper << String.reverse
  • - en funktion med ett icke-alfanumeriskt namn inom parentes skapar en ny operatör
    (#) xy = x * y
    tio = 5 # 2
  • - alla infix-operatörer blir en normal funktion när du lindar den inom parentes
    tio = (+) 5 5
  • - Annoteringar av valfri typ visas ovanför funktionsdeklarationer
    isTen: Int -> Bool
    isTen n = om n == 10 då True annars False

Översikt

Syntax för funktionsapplikationer i Elm använder inte parenteser eller komma, utan är i stället känsliga för mellanrum.

För att definiera en funktion, ange namnet multiplyByTwo och argument x , alla operationer efter lika tecken = är det som returneras från en funktion.

multiplyByTwo x =
    x * 2

För att ringa en funktion anger du dess namn och argument:

multiplyByTwo 2  -- 4

Observera att syntax som multiplyByTwo(2) inte är nödvändigt (även om kompilatorn inte klagar). Parenteserna tjänar bara till att lösa företräde:

> 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-uttryck

Elm har en speciell syntax för lambda-uttryck eller anonyma funktioner:

\arguments -> returnedValue

Såsom exempelvis List.filter i List.filter :

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

Mer till djupet används en bakåtstreck, \ , för att markera början på lambda-uttrycket, och pilen, -> , används för att avgränsa argument från funktionsorganet. Om det finns fler argument, separeras de med ett mellanrum:

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

> normalFunction 1 2
3 : number

> lambdaFunction 1 2
3 : number

Lokala variabler

Det är möjligt att definiera lokala variabler i en funktion till

  • minska kodrepetitionen
  • ge namn till subexpressions
  • minska antalet antagna argument.

Konstruktionen för detta 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!

Definitionens ordning i den första delen av let spelar ingen roll!

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

        y =
            100
    in
        x + y

> outOfOrder
201 : number

Delvis tillämpning

Partiell applikation innebär att man kallar en funktion med mindre argument än den har och sparar resultatet som en annan funktion (som väntar på resten av argumenten).

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

Som en akademisk sidanote kan Elm göra detta på grund av curry bakom kulisserna.

Strikt och försenad utvärdering

I elm beräknas funktionens värde när det sista argumentet tillämpas. I exemplet nedan kommer diagnostik från log att skrivas ut när f åberopas med 3 argument eller en curried form av f tillämpas med det sista argumentet.

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

Ibland vill du förhindra att en funktion används direkt. En typisk användning i Lazy.lazy är Lazy.lazy som ger en abstraktion för att kontrollera när funktioner används.

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

Lazy beräkningar tar en funktion av en () eller Unit typ argument. Enhetstypen är konventionellt typen av ett platshållarargument. I en argumentlista anges motsvarande argument som _ , vilket indikerar att värdet inte används. Enhetsvärdet i alm specificeras av den speciella symbolen () som konceptuellt kan representera en tom tupel eller ett hål. Det liknar den tomma argumentlistan i C, Javascript och andra språk som använder parentes för funktionssamtal, men det är ett vanligt värde.

I vårt exempel kan f skyddas från att utvärderas omedelbart med en 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

Funktionsutvärdering försenas varje gång en funktion delvis tillämpas.

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 har always funktion som inte kan användas för att försena utvärderingen. Eftersom elm utvärderar alla funktionsargument oavsett om och när resultatet av funktionsapplikationen används, kommer en inpackning av en funktionsapplikation always inte att förorsaka en fördröjning, eftersom f tillämpas fullt ut som en parameter för always .

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

Infixoperatörer och infixnotation

Elm tillåter definitionen av anpassade infixoperatörer.

Infix-operatörer definieras med hjälp av parenteser runt namnet på en funktion.

Tänk på detta exempel på infixoperatör för konstruktion Tuples 1 => True -- (1, True) :

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

De flesta av funktionerna i Elm definieras i prefixnotation.

Tillämpa alla funktioner med infixnotation genom att ange det första argumentet före funktionsnamnet bifogat gravt accenttecken:

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
Licensierat under CC BY-SA 3.0
Inte anslutet till Stack Overflow