recursion - F# 递归行为

标签 recursion f#

我最近开始学习 F#,因为我对大多数函数概念都很陌生,所以我倾向于为自己编写一些小示例,并用测试结果检查我的前提。

现在我似乎无法理解以下代码的结果以及它为什么会这样。用例:我掷四个六面骰子,只有当它们的总和大于 20 时才返回它们的总数。

这是我的代码:

let rnd = System.Random()
let d6 () = rnd.Next(1, 7)
let rec foo () =
    // create a list of 4 d6 throws and print out the list
    let numbers = seq { for i in 1 .. 4 -> d6() }
    numbers |> Seq.iter( fun n -> printf "%i " n )
    printfn "\n"

    // sum the list and return the sum only when the sum is greater than 20
    let total = numbers |> Seq.sum
    match total with
    | n when n < 21 -> foo ()
    | _ -> total

现在,当您运行此命令时,您会发现它最终将返回一个大于 20 的数字。

当你查看输出时,你会发现它没有打印出最后一个数字列表,我不明白为什么。

最佳答案

序列是延迟计算的并且不会被缓存。这里发生的情况是,您有一个具有副作用的序列,该序列被多次评估。

第一次评估产生第一个随机数序列:

numbers |> Seq.iter( fun n -> printf "%i " n )

第二次调用再次运行评估,产生完全不同的序列:

let total = numbers |> Seq.sum

如果您想保留第一次评估以多次运行它,您需要做的就是具体化序列或缓存它:

// create a list directly
let numbers = [ for i in 1 .. 4 -> d6() ] 
// or create a list from sequence
let numbers = seq { for i in 1 .. 4 -> d6() } |> List.ofSeq
// or cache the sequence
let numbers = seq { for i in 1 .. 4 -> d6() } |> Seq.cache

关于recursion - F# 递归行为,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/27487685/

相关文章:

java - 使用 return 语句递归打印数字

c++ - 递归函数问题和查找所有可能的路径

python 回溯

f# - 从 F# Fable 调用 ES 3rd 方脚本方法

f# - 带有 EventTarget 的寓言中的语法混淆

reflection - 我可以禁止 F# 编译器在 IL 代码中复制函数吗?

Javascript 修复我的 flatten(array) 函数

java - java中使用递归求数组中正元素的总和

mysql - F# 错误 'error FS0039: The namespace or module ' MySql'未定义'?

F# Monad 如何修复数据类型