Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/drupal/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
F#惰性评估与非惰性评估_F#_Lazy Evaluation - Fatal编程技术网

F#惰性评估与非惰性评估

F#惰性评估与非惰性评估,f#,lazy-evaluation,F#,Lazy Evaluation,我才刚刚开始F#所以如果这是基本的,请客气一点 我已经读到,标记为lazy的函数只计算一次,然后缓存。例如: let lazyFunc = lazy (1 + 1) let theValue = Lazy.force lazyFunc 与每次调用时实际运行的此版本相比: let eagerFunc = (1 + 1) let theValue = eagerFunc 基于此,所有的函数都应该变为惰性吗?你什么时候不想去?这来自于《开始F#》一书中的内容。如果函数执行有副作用,并且每次调用函数

我才刚刚开始F#所以如果这是基本的,请客气一点

我已经读到,标记为lazy的函数只计算一次,然后缓存。例如:

let lazyFunc = lazy (1 + 1)
let theValue = Lazy.force lazyFunc
与每次调用时实际运行的此版本相比:

let eagerFunc = (1 + 1)
let theValue = eagerFunc

基于此,所有的函数都应该变为惰性吗?你什么时候不想去?这来自于《开始F#》一书中的内容。如果函数执行有副作用,并且每次调用函数时都要看到副作用很重要(比如它包装了一个I/O函数),那么您不会希望它懒惰

还有一些函数非常简单,每次执行它们都比缓存值快--

let-quengefunc=(1+1)
是一个let绑定,只执行一次
let func()=(1+1)
是一个接受
单元
(无)并返回
int
的函数。它将在每次调用时执行。从某种意义上说,每个函数都是惰性的,也就是说,它只在被调用时执行。但是,
lazy
关键字(以及它返回的
System.lazy
)将最多执行一次给定给它的表达式/函数。随后调用
属性将返回缓存的结果。当值的计算非常昂贵时,这非常有用


许多函数不适合与
lazy
一起使用,因为它们要么是非确定性的(每次调用可能返回不同的结果),要么是参数化的。当然,可以使用这种函数的完全应用(为每个参数提供一个值)版本,但通常需要可变性。

首先,请注意,您所定义的任何东西都不是函数-
acengerfunc
value
都是
int
类型的值,
lazyFunc
都是
Lazy
类型的值。给定

let lazyTwo = lazy (1 + 1)

表达式
1+1
计算不超过一次,无论您使用
两次
。不同之处在于,定义
2
时,
1+1
将精确计算一次,但在使用
lazytou
时最多计算一次(第一次访问
属性时,将对其进行评估,然后缓存,以便
的进一步使用不需要重新计算)。如果从未访问
Lazytoo
,则其主体
1+1
将永远不会进行评估

通常,在严格的语言(如F#)中使用惰性值不会有多大好处。它们会增加少量开销,因为访问
Value
属性需要检查该值是否已经计算过。如果您有类似
let lazyValue=lazy someVeryExp的内容,它们可能会为您节省一些计算EnsiveCalculationAtMightNotBeneeed()
,因为昂贵的计算只会在实际使用该值的情况下进行。它们还可以使某些算法终止,否则不会终止,但这不是F#中的主要问题。例如:

// throws an exception if x = 0.0
let eagerDivision x =
    let oneOverX = 1.0 / x
    if x = 0.0 then
        printfn "Tried to divide by zero" // too late, this line is never reached
    else
        printfn "One over x is: %f" oneOverX

// succeeds even if x = 0.0, since the quotient is lazily evaluated
let lazyDivision x =
    let oneOverX = lazy (1.0 / x)
    if x = 0.0 then
        printfn "Tried to divide by zero"
    else
        printfn "One over x is: %f" oneOverX.Value

使用
()
不是意味着它是一个函数吗?无论如何,这是好的。你是对的,我的例子非常简单。@恶心-括号在不同的上下文中意味着不同的东西。当你像
(1+1)
那样使用它们时,它们只是用来表示分组和优先级。如果你已经定义了
让func()=…
然后括号表示
eangefunc
是一个函数,但请注意,这与您编写的不同。这是什么版本的F#?我有一个动作迟缓的序列,但不是以那种方式公开创建的。我正试图强制它完成。
// throws an exception if x = 0.0
let eagerDivision x =
    let oneOverX = 1.0 / x
    if x = 0.0 then
        printfn "Tried to divide by zero" // too late, this line is never reached
    else
        printfn "One over x is: %f" oneOverX

// succeeds even if x = 0.0, since the quotient is lazily evaluated
let lazyDivision x =
    let oneOverX = lazy (1.0 / x)
    if x = 0.0 then
        printfn "Tried to divide by zero"
    else
        printfn "One over x is: %f" oneOverX.Value