OCaml 中 Python 枚举函数最简单的模拟是什么?

Mat*_*teo 2 python ocaml list enumerate lazy-sequences

在 Python 中枚举的工作原理如下:

a_list = ['a', 'b', 'c']
    
for i, x in enumerate(a_list): 
    print(i, x)
Run Code Online (Sandbox Code Playgroud)

输出将是:

0 a
1 b
2 c
Run Code Online (Sandbox Code Playgroud)

因此, enumerate 实际上返回一个 (i, x) 形式对的生成器(几乎是一个惰性序列),其中 i 的范围超过 0, 1, 2, ...,x 是列表中按顺序排列的元素。

到目前为止,我已经提出了列表的定义,它不会产生“生成器”,但也会产生一个对的列表:


let enumerate (a_list: 'a list): (int * 'a) list =
  let rec _enumerar (a_list: 'a list) (accum: (int * 'a) list) (i: int): (int * 'a) list =
    match a_list with
    | [] -> accum
    | x::xs -> _enumerar  xs ((i, x)::accum) (i+1)
  in
  _enumerar a_list [] 0 |> List.rev
Run Code Online (Sandbox Code Playgroud)

用法示例:

0 a
1 b
2 c
Run Code Online (Sandbox Code Playgroud)

任何想法是否这个函数可能具有不同的名称在标准库或 Base 中的任何地方实现?

使用序列或流的惰性版本怎么样?

oct*_*ron 6

最简单的 OCaml 等价物是:

List.iteri (Printf.printf "%d %c\n") ['a'; 'b'; 'c']
Run Code Online (Sandbox Code Playgroud)

Python 使用 forloopenumerate是因为它对高阶函数的支持有限。相比之下,OCaml 中的大多数可枚举容器类型倾向于直接提供i迭代器、映射和折叠的版本。

如果您想要从 Python 进行更直接的转换,生成器的 OCaml 版本是 a,Seq.t因为两者都是外部迭代器:

   Seq.iter (fun (i,x) -> Printf.printf "%d %c\n" i x)
@@ Seq.mapi (fun i x -> i, x) 
@@ List.to_seq ['a';'b';'c']
Run Code Online (Sandbox Code Playgroud)

(忘记了OCaml 4.14 中Seq.iteri也存在的时间)

  • 真的。然而,一个区别是“List.mapi”创建了一个中间列表,而“Seq.mapi”和“enumerate”则不是这种情况。 (2认同)