函式

本章節包含必須熟悉的基本 Elm 語法:函式(functions),函式標記式(function signatures),部份套用(partial application)及輸送運算子(pipe operator)。

函式

Elm 支援兩種函式:

  • 匿名函式(anonymous functions)
  • 具名函式(named functions)

匿名函式

顧名思義,函式沒有名稱:

\x -> x + 1

\x y -> x + y

反斜線與箭頭之間為函式引數(arguments),箭頭右邊則是希望函式作的事情。

具名函式

Elm 具名函式看起來像是:

add1 : Int -> Int
add1 x =
  x + 1
  • 範例第一行為函式的標記式。雖然標記式是選擇性(optional)加入,但建議你加入。這會讓你的函式意圖更加清楚。
  • 剩下的部份則是函式的實作。實作必須遵循標記式。

此例中標記式的描述:給定一個整數(Int)作為引數,傳回另一個整數。

呼叫方法:

add1 3

Elm 使用空白(而非括號)來表示函式套用

下面是另一個具名函式:

add : Int -> Int -> Int
add x y =
  x + y

函式取用兩個引數(皆為 Int)並傳回另一個 Int。呼叫函式如下:

add 2 3

無引數

無引數的函式在 Elm 中是一個常數:

name =
  "Sam"

如何套用函式

前述取用兩個引數的函式像是:

divide : Float -> Float -> Float
divide x y =
    x / y

我們可以想像這個函式標記式,取用兩個浮點數引數,傳回另一個浮點數:

divide 5 2 == 2.5

然而,這並不完全正確,Elm 中所有函式都只取得一個引數,傳回一個結果。而結果可以是另一個函式。 以上述的函式解釋。

-- 當我們用:

divide 5 2

-- 評估成:

((divide 5) 2)

-- 首先,評估 `divide 5`。
-- 引數 `5` 套用到 `divide`,傳回一個中間函式。

divide 5 -- -> 中間函式

-- 讓我們稱這個中間函式為 `divide5`。
-- 如果看得到中間函式的標記式及內容,那看起來就像是:

divide5 : Float -> Float
divide5 y =
  5 / y

-- 所以有個函式已經套用了 `5`。

-- 接著套用下一個引數,例如 `2`

divide5 2

-- 這傳回最後結果

這裡不需撰寫括號的原因是,套用函式是從左開始結合

分組括號(Grouping)

當需要呼叫某個函式,其引數值係來自另一個函式的結果,這就需要括號來分組呼叫:

add 1 (divide 12 3)

divide 12 3 傳回的結果作為 add 的第二個引數。

相較之下,其他的語言可能寫成:

add(1, divide(12, 3))

部份套用(Partial application)

如上述說明,每個函式只取一個引數,傳回另一個函式或結果。 表示呼叫類似上述 add 函式帶入一個引數,如 add 2,傳回的是部份套用的函式。 傳回的函式標記式為 Int -> Int

add 2 傳回另一個函式,其中值 2 綁定為第一個引數值。 呼叫傳回的函式並帶入第二個引數值,將傳回 2 + 第二個引數值的結果:

add2 = add 2
add2 3 -- 結果為 5

在 Elm 中部份套用非常有用,讓你的程式碼更好閱讀,並可在應用程式中的函式之間傳遞狀態(state)。

輸送運算子(The pipe operator)

如前述所示,你可以用成巢狀函式,像是:

add 1 (multiply 2 3)

這只是個微不足道的範例,考慮更複雜的範例:

sum (filter (isOver 100) (map getCost records))

這樣的程式碼難以閱讀,因為需要從內到外的解析。輸送運算子讓你撰寫出更好閱讀的程式碼:

3
    |> multiply 2
    |> add 1

這功能非常十分依賴先前提到的部份套用。這個範例中,3 這個值傳遞到部份套用函式 multiply 2。接著,其結果值再傳遞到部份套用函式 add 1

若使用輸送運算子,上述複雜的範例可寫成:

records
    |> map getCost
    |> filter (isOver 100)
    |> sum

results matching ""

    No results matching ""