我想使用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问题-_-)
谢谢
答案 0 :(得分:3)
问题的实质是你没有保存sr
,这会让你检索序列的下一个元素。
但是,稍微大一点的问题是List.init
只将int作为参数传递给初始化函数。因此,即使您确实跟踪sr
,也无法将其传递给初始化函数。
你可以使用OCaml的不纯部分做你想做的事。例如,您可以在每个步骤中将sr
保存在全局引用变量中,并在下次调用初始化函数时检索它。但是,生成列表实际上这是一种非常麻烦的方式。
我建议不使用List.init
。您可以编写一个简单的递归函数来执行您想要的操作。 (如果你关心尾递归,你可以写一个稍微简单的函数。)
答案 1 :(得分:3)
研究List.init
的{{3}}可能有所帮助。
根据列表的大小,有两种变体:尾递归的init_tailrec_aux
,其结果的顺序相反,基本的init_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
。对于严格小于限制的计数器的每个值,它将f i
给出的值添加到正在生成的列表的头部。
现在的问题是,当使用i
的不同值调用时,您的匿名函数会执行什么操作?:
let f_anon =
(fun _i -> match s () with
|Nil -> assert false
|Cons(a, sr) -> a)
无论_i
如何,它总是给出s ()
生成的列表的头部,而如果 s ()
总是返回相同的列表,那么{{ 1}} = f_anon 0
= f_anon 1
= f_anon 2
= f_anon 3
。
hd (s ())
给出不同价值的技巧,我同意他的建议_i
不是解决这个问题的最佳方法
答案 2 :(得分:0)
使用递归函数会增加复杂性,所以我认为直接初始化相应长度的列表(或数组)会更好,但我真的不知道如何在每个_i像Jeffrey那样得到不同的值斯科菲尔德说我对ocaml特别是序列并不熟悉,所以我在做这方面遇到了一些困难:(