Elm严格和延迟的评估

示例

在elm中,当应用最后一个参数时,将计算函数的值。在以下示例中,log当使用3个参数调用f或使用最后一个参数应用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

有时您会希望阻止立即应用某个功能。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.