Eager side effect (printf) in ocaml

孤街醉人 提交于 2019-12-12 06:13:55

问题


Newbie question:

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

回答1:


Effects in Ocaml are eager by default: the language is said to have eager evaluation1, as opposed to so called lazy languages like Haskell.

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) However Ocaml also supports lazy evaluation of some sort through the module Lazy, but evaluation has to be triggered explicitely in certain situations.




回答2:


How about you do the following instead :

let fi = do_sth i in
let () = Printf.printf "%d %d\n" i fi in
fi + loop (i+1)


来源:https://stackoverflow.com/questions/27731647/eager-side-effect-printf-in-ocaml

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!