ocaml 中的 Eager 副作用 (printf)
Eager side effect (printf) in ocaml
新手问题:
假设我有一个非常慢的函数 do_sth
,它适用于范围 1 到 n。我想在循环时打印 do_sth i
的结果。这个怎么做?天真的尝试失败了,因为值只会在整个循环后打印:
let rec loop i =
if i>1000 then 0
else
let fi = do_sth i in
(
Printf.printf "%d %d\n" i fi;
fi + loop (i+1)
)
let f_sum = loop 1
不如改为执行以下操作:
let fi = do_sth i in
let () = Printf.printf "%d %d\n" i fi in
fi + loop (i+1)
Ocaml 中的效果 默认是急切的:据说该语言具有急切的求值1,这与所谓的惰性语言相反像 Haskell.
您看到的结果是由于 stdout
的输出原语完成的缓冲。只需使用 Pervasives.flush stdout
或 Pervasives.flush_all ()
刷新缓冲区即可提供所需的行为。
另外,您可以通过尾递归来优化您的函数:不是在递归调用之后求和,而是将结果累加到函数参数中:
let loop i =
let rec loop r i =
if i>1000 then r
else
let fi = do_sth i in (
Printf.printf "%d %d\n" i fi;
flush stdout;
loop (r+fi) (i+1)
)
in loop 0 i
(1) 然而,Ocaml 也通过模块 Lazy
支持某种惰性求值,但在某些情况下必须显式触发求值。
新手问题:
假设我有一个非常慢的函数 do_sth
,它适用于范围 1 到 n。我想在循环时打印 do_sth i
的结果。这个怎么做?天真的尝试失败了,因为值只会在整个循环后打印:
let rec loop i =
if i>1000 then 0
else
let fi = do_sth i in
(
Printf.printf "%d %d\n" i fi;
fi + loop (i+1)
)
let f_sum = loop 1
不如改为执行以下操作:
let fi = do_sth i in
let () = Printf.printf "%d %d\n" i fi in
fi + loop (i+1)
Ocaml 中的效果 默认是急切的:据说该语言具有急切的求值1,这与所谓的惰性语言相反像 Haskell.
您看到的结果是由于 stdout
的输出原语完成的缓冲。只需使用 Pervasives.flush stdout
或 Pervasives.flush_all ()
刷新缓冲区即可提供所需的行为。
另外,您可以通过尾递归来优化您的函数:不是在递归调用之后求和,而是将结果累加到函数参数中:
let loop i =
let rec loop r i =
if i>1000 then r
else
let fi = do_sth i in (
Printf.printf "%d %d\n" i fi;
flush stdout;
loop (r+fi) (i+1)
)
in loop 0 i
(1) 然而,Ocaml 也通过模块 Lazy
支持某种惰性求值,但在某些情况下必须显式触发求值。