我刚刚开始使用F#并且从15年前的编程语言课程开始就没有真正完成函数式编程(例外情况是“现代”C#)。
我正在使用LINQPad 4查看此F#片段:
let add x y = x + y
let lazyPlusOne x = lazy add x 1
let e = lazyPlusOne 15
Dump e
let plusOne x = add x 1
let f = plusOne 15
Dump f
它产生的输出是:
Lazy<Int32>
Value is not created.
IsValueCreated False
Value 16
16
我理解延迟评估的延迟关键字,直到需要,与C#延迟执行相同。
这里有什么意思:“这里没有创造价值”?
答案 0 :(得分:3)
如果使用lazy
关键字构造惰性值(如lazyPlusOne
函数中所示),则结果为类型Lazy<int>
的值。这表示类型int
的值,仅在实际需要时才进行评估。
我假设Dump
函数尝试打印包含其所有属性的值 - 当它开始打印时,不评估该值,因此ToString
方法打印Value is not created.
然后迭代其他属性,当它访问Value
时,将评估惰性值(因为现在需要它的值)。评估后,该属性返回16,然后打印。
您可以使用F#友好的打印功能替换Dump
(或者只使用F#Interactive,这是使用常规IntelliSense,后台错误检查etec在Visual Studio中使用F#非常方便的方式。)
F#友好的打印功能(如printfn "%A"
)无法访问Value
属性,因此不会意外评估该值。以下是F#Interactive的片段:
> let a = lazy (1 + 2);;
val a : Lazy<int> = Value is not created. // Creates lazy value that's not evaluated
> a;;
val it : Lazy<int> = Value is not created. // Still not evaluated!
> a.Value;; // Now, the lazy value needs to be evaluated (to get the Value)
val it : int = 3
> a;; // After evaluation, the value stays cached
val it : Lazy<int> = 3
答案 1 :(得分:0)
截至'转储e','lazyPlusOne 15'尚未评估。 'let e = lazyPlusOne 15'不需要评估'lazyPlusOne 15'。我们还不需要知道e评估的内容。 转储正在触发评估,并且在语义上不同,只是在评估后转储值。