Ocaml 核心&x27;s`List.init`在渗透式中?
我习惯了JaneStreet的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
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 []
;;