返回列表中所有值的递归函数(在OCaml中)

返回列表中所有值的递归函数(在OCaml中),ocaml,Ocaml,我需要一个函数,在每次迭代时递归返回(而不是打印)列表中的所有值。但是,每次我尝试编写此函数时,我的函数都会返回一个列表 let rec elements list = match list with | [] -> [] | h::t -> h; elements t;; 每次在我编写的另一个函数中返回每个元素时,我都需要使用这些元素,所以我每次需要一个元素,但我无法理解这一部分。任何帮助都将不胜感激。您的功能相当于: let rec elements list = m

我需要一个函数,在每次迭代时递归返回(而不是打印)列表中的所有值。但是,每次我尝试编写此函数时,我的函数都会返回一个列表

let rec elements list = match list with
 | [] -> []
 | h::t -> h; elements t;;

每次在我编写的另一个函数中返回每个元素时,我都需要使用这些元素,所以我每次需要一个元素,但我无法理解这一部分。任何帮助都将不胜感激。

您的功能相当于:

let rec elements list = 
  match list with 
    | [] -> []
    | h :: t -> elements t
这是因为
a;b
计算
a
(并丢弃结果),然后计算并返回
b
。显然,这反过来相当于:

let elements (list : 'a list) = []
这不是一个非常有用的函数

但是,在尝试解决此问题之前,请了解目标Caml函数只能返回一个值。不可能返回多个值

有一些方法可以绕过这个限制。一种解决方案是将所有希望返回的值打包成一个值:通常是一个元组或一个列表。因此,如果需要返回任意数量的元素,可以将它们打包到一个列表中,并让调用代码处理该列表:

let my_function () = [ 1 ; 2; 3; 4 ] in (* Return four values *)
List.iter print_int (my_function ())    (* Print four values *)
另一个不太常见的解决方案是提供函数并在每个结果上调用它:

let my_function action = 
  action 1 ;
  action 2 ;
  action 3 ;
  action 4
in
my_function print_int

这不如返回列表灵活,但可以说更快:列表可以被过滤、排序、存储……

您的问题有点让人困惑-您需要一个返回列表中所有值的函数。返回可变数量值的最简单方法是使用列表!您是否正在尝试模仿Python生成器?OCaml没有任何类似于
yield
,但通常通过“传递”一个函数到值来实现相同的功能(使用
iter
fold
map

您当前编写的内容与Python中的内容相当:

def elements(list):
    if(len(list) == 0):
        return []
    else:
        list[0]
        return elements(list[1:])
如果您正在尝试这样做:

def elements(list):
    if(len(list) > 0):
        yield list[0]
        # this part is pretty silly but elements returns a generator
        for e in elements(list[1:]):
            yield e

for x in elements([1,2,3,4,5]):
    dosomething(x)
OCaml中的等效项如下所示:

List.iter dosomething [1;2;3;4;5]
如果您试图确定列表a是否是列表b的子集(正如我从您的评论中收集的),那么您可以利用
list.mem
list.for_all

List.for_all (fun x -> List.mem x b) a
fun x->List.mem x b
定义了一个函数,如果值x等于b中的任何元素(是b的成员),该函数将返回true<代码>列表。for_all接受一个返回bool(在我们的例子中,是我们刚刚定义的成员函数)和列表的函数。它将该函数应用于列表中的每个元素。如果该函数对列表中的每个值都返回true,则
for_all
返回true


所以我们所做的是:对于a中的所有元素,检查它们是否是b的成员。如果您对如何自己编写这些函数感兴趣,那么我建议您阅读list.ml的源代码,它(假设*nix)可能位于/usr/local/lib/ocaml或/usr/lib/ocaml中。

感谢您的回复。我一直在考虑用两个函数分两步完成这项工作,如您所述,但我的问题是逐个检索每个元素。我应该更具体一点。我的主要功能是一个子集功能,其中我的任务是确定列表a是否是列表b的子集。我被要求以多态的方式编写此函数,但现在我只能知道如何使用int列表来完成此操作。问题是因为我编写了一个函数来返回列表的第一个元素:let head list=match list with h::t->h |[]->0。因为我必须考虑空列表,所以我返回0,OCaml确定此函数接受一个int列表。由于子集函数需要是多态的,所以我无法提前知道为空集返回什么,无论是0、“null”还是其他。因此,这将我限制在整数列表中。在这种情况下(对于空列表返回什么),只需提出一个错误:(failwith“error”)我认为您在这个问题上完全走错了方向。如果您在编写子集函数时遇到困难,我建议您就此提出一个问题-您将得到更清晰、更适合您实际问题的答案(例如
让子集a b=List.for_all(fun I->List.mem I b)a
)以及对您已经编写的代码的建设性评论。