Ocaml 核心&x27;s`List.init`在渗透式中?

Ocaml 核心&x27;s`List.init`在渗透式中?,ocaml,ocaml-core,Ocaml,Ocaml Core,我习惯了JaneStreet的Core库。其列表模块具有整洁的init功能: List.init;; - : int -> f:(int -> 'a) -> 'a list = <fun> 然而,这一功能似乎并不存在于普及版中,这是令人遗憾的。是我遗漏了什么,还是我必须自己实施?如果我真的需要写,我该如何实现 编辑: 我已经编写了一个命令式版本的init,但在这种情况下,使用OCaml的命令式功能是不对的:( 让init n~f= 设i=ref0 in 设l=re

我习惯了JaneStreet的
Core
库。其
列表
模块具有整洁的
init
功能:

List.init;;
- : int -> f:(int -> 'a) -> 'a list = <fun>
然而,这一功能似乎并不存在于
普及版中,这是令人遗憾的。是我遗漏了什么,还是我必须自己实施?如果我真的需要写,我该如何实现

编辑

我已经编写了一个命令式版本的
init
,但在这种情况下,使用OCaml的命令式功能是不对的:(

让init n~f=
设i=ref0 in
设l=ref[]在
而我呢
l:=(f!i)::!l;
增量i;
完成;
List.rev!l
;;
编辑2:

我已经在OCaml的GitHub上打开了一个包含此功能的应用程序

编辑3:


该功能是在OCaml 4.06中发布的。

递归实现相当简单。但是,它不是尾部递归,这意味着您将面临大型列表堆栈溢出的风险:

let init_list n ~f =
  let rec init_list' i n f =
    if i >= n then []
    else (f i) :: (init_list' (i+1) n f)
  in init_list' 0 n f
我们可以使用通常的技术将其转换为尾部递归版本:

let init_list n ~f =
  let rec init_list' acc i n f =
    if i >= n then acc
    else init_list' ((f i) :: acc) (i+1) n f
  in List.rev (init_list' [] 0 n f)
这使用了累加器,还需要反转中间结果,因为列表是反向构造的。请注意,我们也可以使用
f(n-i-1)
而不是
f i
来避免反转列表,但如果
f
有副作用,这可能会导致意外行为

另一种更短的解决方案是简单地使用
Array.init
作为起点:

let init_list n ~f = Array.(init n f |> to_list)

您可以从JaneStreet复制代码并使用它

代码如下所示(但不完全相同):

让init n~f=
如果n<0,则引发(无效的_参数“init”);
让rec循环i累计=
如果i=0,则累加
else回路(i-1)(f(i-1)::累计)
在里面
循环n[]
;;

您可以在core_内核包中找到core_list0.ml中的原始代码。

数组。init
是一个东西,但不是
列表。init
?这是一个遗憾。:(作为一个一般性的评论:不要期望Pervisives提供任何方便。如果您想要一个完整的标准库,您必须使用core或容器或电池(可能还有其他人)目前。是的,我已经注意到了。
let init_list n ~f =
  let rec init_list' acc i n f =
    if i >= n then acc
    else init_list' ((f i) :: acc) (i+1) n f
  in List.rev (init_list' [] 0 n f)
let init_list n ~f = Array.(init n f |> to_list)
let init n ~f =
  if n < 0 then raise (Invalid_argument "init");
  let rec loop i accum =
    if i = 0 then accum
    else loop (i-1) (f (i-1) :: accum)
  in
  loop n []
;;