F#闭包内的懒惰评估

时间:2013-11-27 12:25:48

标签: f# closures lazy-evaluation

这是一个F#闭包。代码示例的灵感来自another question

let isPasswordBetter (newPassword:string) (currPassword:string) =

    let isLongEnough = newPassword.Length > 1

    let newIsLongerThanCurrent = 
        (newPassword.Length > currPassword.Length)

    if isLongEnough then
        if newIsLongerThanCurrent then
            true
        else
            false
    else
        false

let result1 = isPasswordBetter "a" "hello"
let result2 = isPasswordBetter "hellothere" "hello"
let result3 = isPasswordBetter "aaa" "hello"

让我们假设newIsLongerThanCurrent计算成本非常高。

如果我理解正确F# is lazy by default,则意味着newIsLongerThanCurrent将始终在到达if than之前进行评估,即使其评估可能不是必需的。因此,我应该明确地lazy

我的理解是否正确?如果不需要lazy来推迟计算newIsLongerThanCurrent

,我宁愿避免使用杂乱代码

2 个答案:

答案 0 :(得分:3)

尤金在说默认情况下F#懒惰是正确的。在这种情况下,将newIsLongerThanCurrent转换为函数是最好的方法。

通常,F#提供了一种使用lazy关键字添加懒惰的方法。如果您需要多次访问该值,这非常有用(因为它会缓存结果,而多次运行函数会重复运行计算)。

let newIsLongerThanCurrent = 
    lazy (newPassword.Length > currPassword.Length)

if isLongEnough then
    if newIsLongerThanCurrent.Value then                // Computation evaluated here
        let x = newIsLongerThanCurrent.Value || other   // ..the result is reused here
        (...)

答案 1 :(得分:2)

默认情况下,F#是not懒惰的。 最懒惰的“懒惰”方法是将newIsLongerThanCurrent转换为函数:

let newIsLongerThanCurrent() = 
    (newPassword.Length > currPassword.Length)

并将其应用于if - 子句:

if isLongEnough then
    if newIsLongerThanCurrent() then
...