ocaml中的急切副作用(printf) [英] Eager side effect (printf) in ocaml
问题描述
新手问题:
说我有一个非常慢的函数do_sth
,它应用于范围1到n.我想在循环时打印do_sth i
的结果.这该怎么做?天真尝试失败,因为这些值仅在整个循环之后才会打印:
Say I have a function do_sth
that is very slow, and it is applied to range 1 to n. I want to print the result of do_sth i
when it is looping. How to do this? A naive attempt fails as the values will only be printed after the whole loop:
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
推荐答案
默认情况下,Ocaml 中的效果是渴望的:据说该语言具有热情的评价 1 ,因为反对像 Haskell 这样的所谓的惰性语言.
Effects in Ocaml are eager by default: the language is said to have eager evaluation1, as opposed to so called lazy languages like Haskell.
您看到的结果是由于stdout
的输出原语完成的缓冲所致.只需用Pervasives.flush stdout
或Pervasives.flush_all ()
刷新缓冲区即可提供所需的行为.
The result you are witnessing is due to buffering done by output primitives for stdout
. Simply flushing the buffers with Pervasives.flush stdout
or Pervasives.flush_all ()
will provide the desired behaviour.
此外,您可以通过使函数尾部递归来优化函数:在递归调用后不进行求和,而是将结果累加到函数参数中:
Also, you may optimise your function by making it tail recursive: instead of doing the sum after the recursive call, accumulate the result in a function parameter:
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
进行某种形式的延迟评估,但是在某些情况下必须显式触发评估.
(1) However Ocaml also supports lazy evaluation of some sort through the module Lazy
, but evaluation has to be triggered explicitely in certain situations.
这篇关于ocaml中的急切副作用(printf)的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!