F#noob有助于理解懒惰和价值

时间:2011-08-04 18:38:10

标签: f#

我刚刚开始使用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#延迟执行相同。

这里有什么意思:“这里没有创造价值”?

2 个答案:

答案 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评估的内容。 转储正在触发评估,并且在语义上不同,只是在评估后转储值。