Elm Language
関数と部分的なアプリケーション
サーチ…
構文
- - 引数のない関数を定義することは、単純に値を定義することと同じように見えます
言語= "エルム" - - 引数を持たない関数をその名前を記述して呼び出す
言語 - - パラメータはスペースで区切られ、関数の名前に従います
xy = x + yを加算する - - 同じように関数を呼び出す
追加5 2 - - 一部のパラメータのみを提供することによって関数の一部を適用する
増分= 1を加算する - - |演算子を使用して、左の式を右の関数に渡します
10 = 9 |>インクリメント - - <|演算子は右の式を左の関数に渡します
インクリメント<| 5 4を加える - - chain / 2つの関数を>>演算子と共に構成する
backwardsYell = String.reverse >> String.toUpper - - <<は逆方向に同じように動作します
backwardsYell = String.toUpper << String.reverse - - カッコ内の英数字以外の名前を持つ関数は、新しい演算子を作成します
(#)xy = x * y
10 = 5#2 - - 中置演算子はカッコで囲むと通常の関数になります
10 =(+)5 5 - - オプションの型アノテーションは、関数宣言の上に表示されます
isTen:Int - > Bool
isTen n = nが10の場合はTrue、そうでない場合は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では、最後の引数が適用されたときに関数の値が計算されます。以下の例では、fが3つの引数で呼び出された場合、または最後の引数でfのカルト形式が適用された場合に、 logからの診断が出力されます。
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
関数がすぐに適用されないようにすることが時々あります。 elmの典型的な使用法は、関数が適用されるときを制御するための抽象化を提供するLazy.lazyです。
lazy : (() -> a) -> Lazy a
レイジー計算は、1つの()またはUnit type引数の関数をとります。ユニットタイプは通常、プレースホルダ引数の型です。引数リストでは、対応する引数が_として指定され、値が使用されていないことを示します。 elmの単位値は、概念的に空のタプルまたは穴を表すことができる特殊記号()によって指定されます。これは、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機能があり、評価を遅らせることはできません。ニレは関係なく、関数適用の結果がで関数適用を包む、使用されているかどうか、いつのすべての関数の引数を評価しているためalwaysので、遅延が発生することはありませんf完全にパラメータとして適用されalways 。
alwaysF = always (f "a" "b" "c") -- <function> : a -> String
-- Diagnostic: ["a","b","c"] -- Evaluation wasn't delayed.
中置演算子と中置記法
Elmはカスタム中置演算子の定義を可能にします。
中置演算子は、関数の名前のまわりにかっこを使用して定義されます。
この組み込み演算子の構築例を考えてみましょう。タプル1 => True -- (1, True) :
(=>) : a -> b -> ( a, b )
(=>) a b =
( a, b )
Elmの関数のほとんどは接頭辞表記法で定義されています。
アクセント記号で囲まれた関数名の前に最初の引数を指定して、
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]