将序列转换为OCaml中的列表的函数
我想使用list.init将序列转换为列表。我希望在每一步中检索s的第I个值将序列转换为OCaml中的列表的函数,ocaml,Ocaml,我想使用list.init将序列转换为列表。我希望在每一步中检索s的第I个值 let to_list s = let n = length s in List.init n (fun _i -> match s () with |Nil -> assert false |Cons(a, sr) -> a) 这给了我一个仅用s的第一个元素初始化的列表。在OCaml中是否可以使用s的所有值初始化列表,是否需要帮助请注意(关于begginer问题,请原谅-)
let to_list s =
let n = length s in List.init n (fun _i -> match s () with
|Nil -> assert false
|Cons(a, sr) -> a)
这给了我一个仅用s的第一个元素初始化的列表。在OCaml中是否可以使用s的所有值初始化列表,是否需要帮助请注意(关于begginer问题,请原谅-)
谢谢问题的实质是您没有保存
sr
,这将允许您检索序列的下一个元素
然而,稍微大一点的问题是List.init
只将int作为参数传递给初始化函数。因此,即使您跟踪了sr
,也无法将其传递给初始化函数
您可以使用OCaml的不纯部分做您想要做的事情。例如,您可以在每个步骤将sr
保存在全局参考变量中,并在下次调用初始化函数时检索它。然而,这确实是一个相当麻烦的方法来生成您的列表
我建议不要使用List.init
。您可以编写一个简单的递归函数来执行您想要的操作。(如果您关心尾部递归,您可以编写一个稍微不那么简单的函数。)这可能有助于研究List.init的用法
根据列表的大小,有两种变体:一种是尾部递归变量,init\u tailrec\u aux
,其结果顺序相反;另一种是基本变量,init\u aux
。它们具有相同的结果,因此我们只需查看init_aux
:
let rec init_aux i n f =
if i >= n then []
else
let r = f i in
r :: init_aux (i+1) n f
此函数递归递增计数器i
,直到达到限制n
。对于严格小于限制的每个计数器值,它将fi
给出的值添加到正在生成的列表的头部
现在的问题是,当使用不同的i
值调用匿名函数时,它会做什么
let f_anon =
(fun _i -> match s () with
|Nil -> assert false
|Cons(a, sr) -> a)
不管\u i
,它总是给出由s()
生成的列表的标题,如果s()
总是返回相同的列表,那么f\u anon 0
=f\u anon 1
=f\u anon 2
=f\u anon 3
=hd(s())
Jeffrey Scofield描述了一种在每个\u i
处提供不同值的技术,我同意他的建议,即List.init
不是解决此问题的最佳方案。使用递归函数将增加复杂性,因此我认为直接初始化列表(或数组)在相应的长度上会更好,但我真的不知道如何在每个位置获得不同的值,我喜欢Jeffrey Scofield说我对ocaml不太熟悉,尤其是序列,所以我在这方面有一些困难:(谢谢你的回答,是的,我这么做了,但我想知道init是如何工作的,因为我以前没有使用过它,特别是当我们每次都想恢复不同的值时,List.init几乎只适用于列表中的元素可以根据它们在列表中的位置来计算的情况由于您的案例不是这样的,所以弄清楚如何使用List.init
并没有任何好处(IMHO)。相反,您可以尝试使用List.init
将数组转换为列表(例如)@maya如果你想要恢复的值不是0..n-1
范围内的索引整数,其中n
是List.init
的第一个参数,那么就像Jeffrey说的那样,这是一种相当自我挫败的行为。尝试使用下面描述的init_aux
函数,并用序列s
替换f
。s
的头给出了r
,它的尾应该传递给递归调用。使用递归不会增加复杂性。List.init
作为递归函数实现。递归是OCaml中解决问题的正常方法。(但我承认,你确实需要学会识别和使用尾部递归。)@maya soft提醒:请将此作为评论而不是答案发布,否则可能会被标记为稍后删除。