F#惰性评估与非惰性 [英] F# Lazy Evaluation vs Non-Lazy

查看:98
本文介绍了F#惰性评估与非惰性的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我刚开始使用F#,所以如果这很简单,请保持警惕.

I'm just beginning F# so please be kind if this is basic.

我已经读过一个标记为lazy的函数只被评估一次,然后被缓存.例如:

I've read that a function marked lazy is evaluated only once and then cached. For example:

let lazyFunc = lazy (1 + 1)
let theValue = Lazy.force lazyFunc

与此版本相比,该版本实际上在每次调用时都会运行:

Compared to this version which would actually run each time it's called:

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

基于此,所有功能是否应该变得懒惰?您什么时候不想?这来自开始F#" 一书中的内容.

Based on that, should all functions be made lazy? When would you not want to? This is coming from material in the book "Beginning F#".

推荐答案

首先,可能要注意一点,您定义的所有内容都不是函数-eagerFunctheValue都是类型的值intlazyFuncLazy<int>类型的值.给定

First of all, it may be helpful to note that none of the things you have defined is a function - eagerFunc and theValue are values of type int and lazyFunc is a value of type Lazy<int>. Given

let lazyTwo = lazy (1 + 1)

let eagerTwo = 1 + 1

无论您使用eagerTwo多少次,表达式1 + 1都会不会被多次评估.区别在于1 + 1在定义 eagerTwo时将被精确评估一次,但是在lazyTwo时将被评估一次 一次. 已使用(将在第一次访问Value属性时进行评估,然后将其缓存,以便Value的进一步使用不需要重新计算它).如果lazyTwoValue从未被访问过,则其主体1 + 1从不被评估.

the expression 1 + 1 will not be evaluated more than once no matter how many times you use eagerTwo. The difference is that 1 + 1 will be evaluated exactly once when defining eagerTwo, but will be evaluated at most once when lazyTwo is used (it will be evaluated the first time that the Value property is accessed, and then cached so that further uses of Value do not need to recalculated it). If lazyTwo's Value is never accessed, then its body 1 + 1 will never be evaluated.

通常,以严格的语言(例如F#)使用懒惰值不会带来太大好处.由于访问Value属性需要检查该值是否已计算,因此它们会增加少量开销.如果您使用类似let lazyValue = lazy someVeryExpensiveCalculationThatMightNotBeNeeded()的方法,它们可能会为您节省一些计算时间,因为昂贵的计算仅在实际使用该值的情况下才会进行.他们还可以使某些算法终止,否则将无法终止,但这在F#中不是主要问题.例如:

Typically, you won't see much benefit to using lazy values in a strict language like F#. They add a small amount of overhead since accessing the Value property requires checking whether the value has already been calculated. They might save you a bit of calculation if you have something like let lazyValue = lazy someVeryExpensiveCalculationThatMightNotBeNeeded(), since the expensive calculation will only take place if the value is actually used. They can also make some algorithms terminate which otherwise would not, but this is not a major issue in F#. For instance:

// 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

这篇关于F#惰性评估与非惰性的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆