Recursion 将累加器保持在OCaml上实现一个函数

Recursion 将累加器保持在OCaml上实现一个函数,recursion,ocaml,accumulate,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 ;; 其实质是在处

我编写了一个函数,在列表中指定字符串的长度。例如,当用户输入
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的函数:

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:


对于上面的
double\u acc
,内部调用需要一个额外的
[]
参数,并且需要使用
List.rev
反转结果。我想这是一个家庭作业练习,让您自己来解决实际问题。

如果我使用累加器约束:

    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) ) )

用包装器怎么做?我更新了答案。如果您还有更多问题,您应该提供一些您编写的代码。挑剔:您的
wrap_sin
函数计算
|sin|。谢谢,我将切换到sin^2 x。使用累加器使函数尾部递归,这有助于在输入列表较大时避免堆栈溢出。如果手动处理递归,则需要累加器,但是如果您使用标准列表库,那么在示例rev_map为tail recursive的情况下,许多函数已经提供了tail recursive,而不需要您处理累加器。
    let stringy lst = 
       lst
       |> List.map (fun s -> ((String.sub s 0 1),(String.length s) ) )