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

时间:2011-01-13 10:09:52

标签: ocaml

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

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

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

2 个答案:

答案 0 :(得分:3)

您的功能相当于:

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

这比返回列表更灵活,但可能更快:列表可以过滤,排序,存储...

答案 1 :(得分:1)

您的问题有点令人困惑 - 您需要一个能够返回列表中所有值的函数。那么返回可变数量值的最简单方法是使用列表!您是否可能尝试模拟Python生成器? OCaml与yield没有任何相似之处,但通常通过将函数“传递”到值(使用iterfoldmap)来完成相同的操作。

您目前所编写的内容与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.memList.for_all

List.for_all (fun x -> List.mem x b) a

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

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