【问题标题】:Return index of an asked-for value of a list using fold in OCaml在 OCaml 中使用折叠返回列表的请求值的索引
【发布时间】:2014-03-27 19:53:00
【问题描述】:

我写了一个递归版本的index如下

let index list value =
  let rec counter num = function
    | [] -> -1
    | h::t -> 
        if h == value 
          then num 
        else (counter (num + 1)) t
  in counter 0 list;;

它有效,但后来我们的教授说我们应该使用尾递归版本以便在服务器上不超时,所以我使用 fold 编写了一个新的索引函数,但我似乎无法弄清楚为什么如果它没有'找不到元素,它返回一个大于列表长度的数字,即使我希望它返回 -1。

let index2 list value = fold (fun i v -> 
  if i > (length list) then -1
  else if v == value then i                          
  else i+1) 0 list;;

这也是我的折叠版本:

let rec fold f a l = match l with
    [] -> a
  | (h::t) -> fold f (f a h) t;;

【问题讨论】:

  • == 是物理上的平等(这对整数来说很好),但你可能想要=
  • 您对index 的实现是尾递归的。

标签: functional-programming ocaml fold higher-order-functions


【解决方案1】:

您的折叠函数会为列表中的每个元素调用一次。因此,您永远不会看到大于 (length list - 1)i 值。

作为旁注,继续计算列表的长度是非常低效的(二次复杂度)。最好在一开始就计算一次。

另一方面,您几乎不想使用== 运算符。请改用= 运算符。

【讨论】:

    【解决方案2】:

    编辑

    为什么要重新定义fold 而不是使用List.fold_left

    您的第一个版本的索引已经是尾递归的,但您可以通过以下方式改进它的样式:

    • 使用option 类型而不是如果未找到则返回-1;
    • 直接递归调用索引而不是计数函数;
    • 使用=(结构)比较器而不是==(物理);
    • 在模式匹配中使用保护而不是 if 语句。

    所以

    let index list value =
      let rec index' list value i = match list with
        | [] -> None
        | h :: _ when h = value -> Some i
        | _ :: t -> index' t value (succ i)
      in index' list value 0
    

    正如已经说过的,index2 不起作用,因为您永远不会到达索引大于列表长度的元素,因此您只需将 i > (length list) 替换为 i = (length list) - 1 即可使其工作.

    但是index2 的效率低于index,因为index 会在找到元素后立即停止,而index2 总是评估列表中的每个元素并每次将列表长度与计数器进行比较。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2021-12-17
      • 1970-01-01
      • 2013-10-24
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-03-16
      • 2019-08-01
      相关资源
      最近更新 更多