在OCaml上实现保持累加器的功能

时间:2017-10-24 16:07:13

标签: recursion ocaml accumulate

我写了一个函数,给出了列表中字符串的长度。例如,当用户输入stringy ["a";"bbb";"cc";"ddddd"]时。它返回[("a",1); ("bbb",3); ("cc",2); ("ddddd",5)]。我想用累加器做同样的功能。我怎样才能做到这一点 ?

let rec stringy lst =
    match lst with 
    | [] -> []
    | x::xs ->  (x, String.length x) ::stringy xs ;; 

2 个答案:

答案 0 :(得分:1)

本质上是为处理输入列表时收集答案的函数添加另一个参数。

这是一个将列表的每个元素乘以2的函数:

let rec double list =
    match list with
    | [] -> []
    | h :: t -> (h * 2) :: double t

这与累加器的功能相同:

let rec double_acc accum list =
    match list with
    | [] -> accum
    | h :: t -> double_acc ((2 * h) :: accum) t

这第二个版本有两个问题:(1)它需要一个额外的参数,这对调用者来说并不重要; (2)它以相反的顺序返回列表。您可以通过编写添加额外参数的包装函数来解决这些问题,然后使用List.rev反转结果。

<强>更新

包装器函数只是一个调用另一个函数的函数,可能会调整参数和返回值。

这是一个包装函数,通过包装 cos 来计算 sin ^ 2

 let wrap_sin2 theta =
     let cos_theta = cos theta in
     1.0 -. cos_theta *. cos_theta

对于上面的double_acc,内部调用需要额外的[]参数,并且需要使用List.rev反转结果。我留给你弄清楚如何处理你的实际问题,因为我怀疑这是一个家庭作业。

答案 1 :(得分:0)

如果我使用累加器约束:

    let stringy lst = 
       lst
       |> List.fold_left (fun a s -> ((String.sub s 0 1),(String.length s) ) :: a ) []
       |> List.rev

但是你为什么要使用累加器?

另一种方式:

    let stringy lst = 
       lst
       |> List.map (fun s -> ((String.sub s 0 1),(String.length s) ) )