ocaml急切的副作用(printf)

时间:2015-01-01 14:28:05

标签: 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

2 个答案:

答案 0 :(得分:5)

默认情况下,Ocaml 中的效果非常渴望:据说该语言具有急切的评估 1 ,而不是像 Haskell

您目击的结果是由stdout的输出原语完成的缓冲。只需使用Pervasives.flush stdoutPervasives.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进行某种延迟评估,但在某些情况下必须明确触发评估。

答案 1 :(得分:0)

你如何做以下事情:

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