ocaml中的急切副作用(printf) [英] Eager side effect (printf) in ocaml

查看:118
本文介绍了ocaml中的急切副作用(printf)的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

新手问题:

说我有一个非常慢的函数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 stdoutPervasives.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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆