Szukaj…


Składnia

  • - zdefiniowanie funkcji bez argumentów wygląda tak samo jak zwykłe zdefiniowanie wartości
    language = "Elm"
  • - wywołanie funkcji bez argumentów poprzez podanie jej nazwy
    język
  • - parametry są oddzielone spacjami i są zgodne z nazwą funkcji
    dodaj xy = x + y
  • - wywołać funkcję w ten sam sposób
    dodaj 5 2
  • - częściowo zastosować funkcję, podając tylko niektóre jej parametry
    przyrost = dodaj 1
  • - użyj operatora |>, aby przekazać wyrażenie po lewej stronie do funkcji po prawej stronie
    dziesięć = 9 |> przyrost
  • - <| operator przekazuje wyrażenie po prawej stronie do funkcji po lewej stronie
    przyrost <| dodaj 5 4
  • - połącz / skomponuj dwie funkcje razem z operatorem >>
    backwardsYell = String.reverse >> String.toUpper
  • - << działa tak samo w odwrotnym kierunku
    backwardsYell = String.toUpper << String.reverse
  • - funkcja o niealfanumerycznej nazwie w nawiasie tworzy nowego operatora
    (#) xy = x * y
    dziesięć = 5 # 2
  • - dowolny operator infix staje się normalną funkcją po zawinięciu go w nawiasy
    dziesięć = (+) 5 5
  • - opcjonalne adnotacje typu pojawiają się nad deklaracjami funkcji
    isTen: Int -> Bool
    isTen n = jeśli n == 10 to Prawda, inaczej Fałsz

Przegląd

Składnia aplikacji funkcji w Elm nie używa nawiasów ani przecinków i jest wrażliwa na spacje.

Aby zdefiniować funkcję, podaj jej nazwę multiplyByTwo i argumenty x , wszelkie operacje po znaku równości = są zwracane z funkcji.

multiplyByTwo x =
    x * 2

Aby wywołać funkcję, podaj jej nazwę i argumenty:

multiplyByTwo 2  -- 4

Zauważ, że składnia taka jak multiplyByTwo(2) nie jest konieczna (nawet jeśli kompilator nie narzeka). Nawiasy służą jedynie do ustalenia pierwszeństwa:

> 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

Wyrażenia lambda

Wiąz ma specjalną składnię dla wyrażeń lambda lub funkcji anonimowych:

\arguments -> returnedValue

Na przykład, jak widać w List.filter :

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

Bardziej do głębi, ukośnik, \ , służy do oznaczenia początku wyrażenia lambda, a strzałka, -> , służy do oddzielenia argumentów od treści funkcji. Jeśli argumentów jest więcej, są one oddzielane spacją:

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

> normalFunction 1 2
3 : number

> lambdaFunction 1 2
3 : number

Zmienne lokalne

Możliwe jest zdefiniowanie lokalnych zmiennych wewnątrz funkcji do

  • zmniejszyć liczbę powtórzeń kodu
  • nadaj nazwę podwyrażeniom
  • zmniejszyć liczbę przekazywanych argumentów.

Konstrukcja do tego jest 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!

Kolejność definicji w pierwszej części let nie ma znaczenia!

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

        y =
            100
    in
        x + y

> outOfOrder
201 : number

Częściowe zastosowanie

Częściowa aplikacja oznacza wywołanie funkcji z mniejszą liczbą argumentów i zapisanie wyniku jako innej funkcji (która czeka na resztę argumentów).

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

Jako akademicki sidotum, Elm może to zrobić z powodu curry za kulisami.

Ścisła i opóźniona ocena

W wiązie wartość funkcji jest obliczana po zastosowaniu ostatniego argumentu. W poniższym przykładzie diagnostyka z log zostanie wydrukowana, gdy f zostanie wywołany z 3 argumentami lub zastosowana zostanie curry forma f z ostatnim argumentem.

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

Czasami chcesz uniemożliwić zastosowanie funkcji od razu. Typowym zastosowaniem w Lazy.lazy jest Lazy.lazy który zapewnia abstrakcję do kontrolowania, kiedy funkcje są stosowane.

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

Leniwe obliczenia przyjmują funkcję jednego () lub argumentu typu Unit . Typ jednostki to typowo argument zastępczy. Na liście argumentów odpowiedni argument jest określony jako _ , co oznacza, że wartość nie jest używana. Wartość jednostki w wiązie jest określona specjalnym symbolem () który może koncepcyjnie przedstawiać pustą krotkę lub dziurę. Przypomina pustą listę argumentów w C, JavaScript i innych językach, które używają nawiasów do wywołań funkcji, ale jest to zwykła wartość.

W naszym przykładzie f można zabezpieczyć przed natychmiastową oceną za pomocą 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

Ocena funkcji jest opóźniona za każdym razem, gdy funkcja jest częściowo zastosowana.

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

Wiąz ma always funkcję, której nie można użyć do opóźnienia oceny. Ponieważ wiąz ocenia wszystkie argumenty funkcji niezależnie od tego, czy i kiedy zostanie użyty wynik zastosowania aplikacji funkcji, zawijanie aplikacji funkcji always nie spowoduje opóźnienia, ponieważ f jest w pełni stosowane jako parametr do always .

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

Operatory i notacja infix

Wiąz pozwala na zdefiniowanie niestandardowych operatorów infix.

Operatory Infix są definiowane za pomocą nawiasów wokół nazwy funkcji.

Rozważ ten przykład operatora infix dla konstrukcji Tuples 1 => True -- (1, True) :

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

Większość funkcji w Elm jest zdefiniowana w notacji przedrostkowej.

Zastosuj dowolną funkcję za pomocą notacji niecałkowitej, podając pierwszy argument przed nazwą funkcji ujętą w poważny znak akcentujący:

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
Licencjonowany na podstawie CC BY-SA 3.0
Nie związany z Stack Overflow