嚴格和延遲的評估
在 elm 中,在應用最後一個引數時計算函式的值。在下面的示例中,當使用 3 個引數呼叫 f 或使用最後一個引數應用 f 的 curry 形式時,將列印 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
延遲計算採用一個 ()
或 Unit
型別引數的函式。單位型別通常是佔位符引數的型別。在引數列表中,相應的引數指定為 _
,表示未使用該值。elm 中的單位值由特殊符號 ()
指定,它可以在概念上表示空元組或空洞。它類似於 C,Javascript 和其他使用括號進行函式呼叫的語言中的空引數列表,但它是一個普通值。
在我們的例子中,可以保護 f
不被 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
只要部分應用功能,功能評估就會延遲。
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.