在 OCAML 循环中添加要列出的元素

Era*_*s H 1 ocaml loops list

您好,我是 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] 应该有类型单位。当我调用此函数时,它返回一个空列表。谁能帮我 ?谢谢

H. *_*ich 6

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)

这个变体是高效的,尾递归的,但更难阅读(恕我直言)。

最后,您可能需要查看ExtLibBatteries中的Queue 模块或DynArray 模块。