您好,我是 OCAML 的初学者,我想创建一个函数来在列表末尾添加元素并返回此列表。这是我的代码:
let test () : int list =
let mylist = [] in
for i = 1 to 3 do
mylist@[i];
done;
mylist;;
Run Code Online (Sandbox Code Playgroud)
它说 mylist@[i] 应该有类型单位。当我调用此函数时,它返回一个空列表。谁能帮我 ?谢谢
Ocaml 列表是不可变的,即它们不能更改。表达方式
mylist@[i]
Run Code Online (Sandbox Code Playgroud)
创建一个新列表。但是,由于您对结果不做任何操作,因此它会被丢弃。如果您想构建这样的列表,则需要将其存储在引用中。
let l = ref [] in
for i = 0 to 3 do
l := !l @ [i]
done;
List.iter (fun item -> print_int item; print_newline ()) !l
Run Code Online (Sandbox Code Playgroud)
不过,我建议采取不同的做法。追加两个列表是一项相当昂贵的操作,因为每次都会创建一个新列表并且复制所有元素。一种更有效的方法是按相反的顺序创建列表并使用List.cons(:: 运算符),这会将新元素添加到列表的开头。
let l = ref [] in
for i = 3 downto 0 do
l := i :: !l
done;
List.iter (fun item -> print_int item; print_newline ()) !l
Run Code Online (Sandbox Code Playgroud)
该cons操作以恒定时间运行,因为它可以重用已经存在的列表。
或者,您也可以使用递归创建列表。
let rec l i =
if i <= 3 then i :: l (i+1) else [] in
List.iter (fun item -> print_int item; print_newline ()) (l 0)
Run Code Online (Sandbox Code Playgroud)
该变体也不需要复制列表,但它不是尾递归的,即它使用与列表中的元素一样多的堆栈空间。
let rec l acc i =
if i >= 0 then l (i :: acc) (i-1) else acc in
List.iter (fun item -> print_int item; print_newline ()) (l [] 3)
Run Code Online (Sandbox Code Playgroud)
这个变体是高效的,尾递归的,但更难阅读(恕我直言)。
最后,您可能需要查看ExtLib或 Batteries中的Queue 模块或DynArray 模块。