5

我正在阅读一些笔记,发现这段代码对我来说看起来很干净:

# let sigma f m =
  let rec sum (i, z) =
  if i = m then z else sum(i+1, z+.f i)
  in sum(0, 0.0);;
val sigma : (int -> float) -> int -> float = <fun>
# sigma (function k -> float (k*k)) 10;;
- : float = 285.

我明白每一点,除了有的部分in sum(0, 0.0)。好吧,问题实际上不在于in关键字,而在于:sum(0, 0.0). 这应该是什么意思,为什么这个功能有用?我做了一些谷歌搜索,并in从 Ocaml 网站获得了一些关于关键字的信息,但这对我来说毫无意义。这是我发现的:

class-expr  ::= class-path  
    ∣     [ typexpr  {, typexpr} ]  class-path  
    ∣     ( class-expr )  
    ∣     ( class-expr :  class-type )  
    ∣     class-expr  {argument}+  
    ∣     fun {parameter}+ ->  class-expr  
    ∣     let [rec] let-binding  {and let-binding} in  class-expr  
    ∣     object class-body end  

我不需要对实际功能的解释。我需要帮助的是那么小in sum(0, 0.0)

4

1 回答 1

10

它是let 绑定 in ;你in的与let rec sum

所以内部

let rec sum (i, z) =
if i = m then z else sum(i+1, z+.f i)
in sum(0, 0.0);;

是一个内部尾递归函数,用于循环,sum(0,0.0)(具有该内部sum定义)的结果是sigma函数的结果。

是尾递归的sum(0,0.0)起点。

我建议你使用 Ocaml 的调试器,或者至少添加一个

 Printf.printf "sum i=%d z=%f\n";

就在该let rec sum(i,z) =行之后。

顺便说一句,你应该用两个参数编码一个总和,而不是一个参数恰好是一对:

let rec sum i  z =
if i = m then z else sum(i+1) (z+.f i)
in sum 0 0.0;;

顺便说一句,我会用递减i和代码循环

let sigma f m = 
  let rec sumloop i s = 
     (* Printf.printf "sumloop i=%d s=%f\n" i s ; *)
     if (i <= 0) then s
     else sumloop (i-1) (s+.f i)
  in sumloop m 0.0 ;;

我同意我的sigma函数略有不同(特别是如果参数f是具有副作用的不纯函数)。我命名了内部尾递归函数sumloop(不仅仅是sum),以强调它是一个循环。

你的z正式到sum和我的s正式到sumloop是一个累积的部分和。

于 2013-10-27T20:04:08.340 回答