Elm Language
Функции и частичное применение
Поиск…
Синтаксис
- - определение функции без аргументов выглядит так же, как просто определение значения
язык = "Elm" - - вызов функции без аргументов путем указания ее имени
язык - - параметры разделяются пробелами и следуют имени функции
добавьте xy = x + y - - вызвать функцию таким же образом
добавить 5 2 - - частично применять функцию, предоставляя лишь некоторые из ее параметров
increment = add 1 - - используйте оператор |>, чтобы передать выражение слева функции справа
ten = 9 |> приращение - - <| оператор передает выражение справа на функцию слева
приращение <| добавить 5 4 - - цепь / составьте две функции вместе с оператором >>
backwardsYell = String.reverse >> String.toUpper - - << работает одинаково в обратном направлении
назадYell = String.toUpper << String.reverse - - функция с не-буквенно-цифровым именем в круглых скобках создает новый оператор
(#) xy = x * y
десять = 5 # 2 - - любой инфиксный оператор становится нормальной функцией, когда вы завертываете его в круглые скобки
десять = (+) 5 5 - - необязательные аннотации типов отображаются над объявлениями функций
isTen: Int -> Bool
isTen n = if n == 10 then True else False
обзор
Синтаксис синтаксиса приложения в Elm не использует скобки или запятые и, вместо этого, чувствителен к пробелам.
Чтобы определить функцию, укажите ее имя multiplyByTwo и аргументы x , любые операции после равенства знак = это то, что возвращается из функции.
multiplyByTwo x =
x * 2
Чтобы вызвать функцию, укажите ее имя и аргументы:
multiplyByTwo 2 -- 4
Обратите внимание, что синтаксис, такой как multiplyByTwo(2) , не требуется (даже если компилятор не жалуется). Скобки предназначены только для устранения приоритета:
> 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
Лямбда-выражения
Elm имеет специальный синтаксис для лямбда-выражений или анонимных функций:
\arguments -> returnedValue
Например, как показано в List.filter :
> List.filter (\num -> num > 1) [1,2,3]
[2,3] : List number
Больше, чем глубина, обратная косая черта \ , используется для обозначения начала лямбда-выражения, а стрелка -> используется для разграничения аргументов из тела функции. Если есть больше аргументов, они разделяются пробелом:
normalFunction x y = x + y
-- is equivalent to
lambdaFunction = \x y -> x + y
> normalFunction 1 2
3 : number
> lambdaFunction 1 2
3 : number
Местные переменные
В локальной функции можно определить локальные переменные
- сократить повторение кода
- давать имя подвыражениям
- уменьшите количество переданных аргументов.
Конструкция для этого 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!
Порядок определений в первой части let не имеет значения!
outOfOrder =
let
x =
y + 1 -- the compiler can handle this
y =
100
in
x + y
> outOfOrder
201 : number
Частичное применение
Частичное приложение означает вызов функции с меньшими аргументами, чем она, и сохранение результата в качестве другой функции (которая ждет остальных аргументов).
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
В качестве академического подхода, Элм может это сделать из-за карьеры за кулисами.
Строгая и отсроченная оценка
В elm значение функции вычисляется при применении последнего аргумента. В приведенном ниже примере диагностика из log будет напечатана, когда f вызывается с 3 аргументами или применяется кардинальная форма f с последним аргументом.
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
Время от времени вы хотите, чтобы функция сразу не была применена. Типичным использованием в вяз является Lazy.lazy который обеспечивает абстракцию для контроля при применении функций.
lazy : (() -> a) -> Lazy a
Ленивые вычисления принимают функцию одного () или аргумента типа Unit . Тип блока обычно является типом аргумента-заполнителя. В списке аргументов соответствующий аргумент указан как _ , указывая, что значение не используется. Значение единицы в вязе определяется специальным символом () который может концептуально представлять пустой кортеж или отверстие. Он похож на пустой список аргументов на языках C, Javascript и других языках, которые используют скобки для вызовов функций, но это обычное значение.
В нашем примере f может быть защищен от немедленной оценки с помощью лямбда:
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
Оценка функции задерживается в любое время, когда функция частично применяется.
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 always функция, которая не может использоваться для задержки оценки. Поскольку elm оценивает все аргументы функции независимо от того, используется ли и когда результат применения функции, то приложение приложения always вызывает задержку, так как f полностью применяется как параметр always .
alwaysF = always (f "a" "b" "c") -- <function> : a -> String
-- Diagnostic: ["a","b","c"] -- Evaluation wasn't delayed.
Операторы Infix и инфиксная нотация
Elm позволяет определять пользовательские операторы infix.
Операторы Infix определяются с помощью скобок вокруг имени функции.
Рассмотрим этот пример инфиксного оператора для построения Tuples 1 => True -- (1, True) :
(=>) : a -> b -> ( a, b )
(=>) a b =
( a, b )
Большинство функций в Elm определены в префиксной нотации.
Примените любую функцию, используя нотацию infix, указав первый аргумент перед именем функции, заключенным с символом серьезного акцента:
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]