ocaml - OCaml 中 `let rec` 绑定(bind)与常规 `let` 绑定(bind)的优势

标签 ocaml

这个问题是这个 SO 问题的后续问题:How to make a covariant observable in OCaml

接受的答案的作者(随便)注意到使用 let rec绑定(bind)两个独立的值比两个单独的值更“经济”let绑定(bind)。

let make x =
  let queue = Queue.create () in
  let obj = x in
  let watch f = Queue.add f queue in
  let notify () = Queue.iter (fun f -> f x) queue in
  { obj; watch; notify; }

对比
let make x =
  let queue = Queue.create () in
  let obj = x in
  let rec watch f = Queue.add f queue
  and notify () = Queue.iter (fun f -> f x) queue in
  { obj; watch; notify; }

他的说法正确吗?如果是这样,为什么第二个版本更“经济”?

最佳答案

正如我在评论中已经说过的,似乎通过使用 let rec ,您可以避免创建更多的闭包。为了检查这一点,我创建了两个略有不同的文件,如下所示:
test1.ml有没有 let rec 的“通常”方式:

let test1 x =
    let x = 5 in
    let w () = x + 1 in
    let n () = x + 1 in
    w () + n ()

另一方面,test2.ml使用 let rec :
let test2 x =
    let x = 5 in
    let rec w () = x + 1 
    and n () = x + 1 in
    w () + n ()

我然后ocamlc -dinstr 'd 两个文件(即我为两个文件生成字节码)并获得以下内容:

对于 test1.ml , 我有:
    branch L2
L3: envacc 1
    offsetint 1
    return 1
L4: envacc 1
    offsetint 1
    return 1
L1: const 5
    push
    acc 0
    closure L4, 1
    push
    acc 1
    closure L3, 1
    push
    const 0a
    push
    acc 1
    apply 1
    push
    const 0a
    push
    acc 3
    apply 1
    addint
    return 4
L2: closure L1, 0
    push
    acc 0
    makeblock 1, 0
    pop 1
    setglobal Closuretest!

文件test2.ml结果如下:
    branch L2
L3: envacc 3
    offsetint 1
    return 1
L4: envacc 1
    offsetint 1
    return 1
L1: const 5
    push
    acc 0
    closurerec 3 4, 1
    const 0a
    push
    acc 1
    apply 1
    push
    const 0a
    push
    acc 3
    apply 1
    addint
    return 4
L2: closure L1, 0
    push
    acc 0
    makeblock 1, 0
    pop 1
    setglobal Closuretest2!

来自 Caml Virtual Machine — Instruction set Document (可惜我也不知道是不是官方的,不过看起来还是有道理的),貌似说明书closureclosurerec在堆栈上生成一个闭包。如您所见,test1.ml 的字节码总共生成 3 个闭包,而 test2.ml只生成两个闭包(一个通过 closurerec )。

我不是组装大师,但你可以测试ocamlopt -S filename.ml ,以便编译器留下(并且不删除)程序集(然后在 filename.s 中),您也可以在其中发现类似的差异。

关于ocaml - OCaml 中 `let rec` 绑定(bind)与常规 `let` 绑定(bind)的优势,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/21500537/

相关文章:

ocaml - OCaml 中的 Trie 数据结构

functional-programming - 了解多提示分隔的延续的 API

algorithm - 层次二叉树遍历的魔法代码——发生了什么?

ocaml - 将 OCaml 字符串转换为 format6

python - OCaml mod 函数返回与 % 不同的结果

for-loop - OCaml - If 语句内的 For 循环

ocaml - 寻找迭代 ocaml 类型构造函数的技巧

functional-programming - 如何使 `fun [x] -> x` 详尽无遗?

asynchronous - F#:相当于 OCaml 异步

ocaml 内存在应用于斐波那契数列时失败