开发者

Recursive function that returns all values in list (In OCaml)

I need a function that recursively returns (not prints) all values in a list with each iteration. However, every time I try programming this my function ret开发者_运维百科urns a list instead.

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

I need to use each element each time it is returned in another function that I wrote, so I need these elements one at a time, but I can't figure this part out. Any help would be appreciated.


Your function is equivalent to :

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

This happens because a ; b evaluates a (and discards the result) and then evaluates and returns b. Obviously, this is in turn equivalent to:

let elements (list : 'a list) = []

This is not a very useful function.

Before you try solving this, however, please understand that Objective Caml functions can only return one value. Returning more than one value is impossible.

There are ways to work around this limitation. One solution is to pack all the values you wish to return into a single value: a tuple or a list, usually. So, if you need to return an arbitrary number of elements, you would pack them together into a list and have the calling code process that list:

let my_function () = [ 1 ; 2; 3; 4 ] in (* Return four values *)
List.iter print_int (my_function ())    (* Print four values *)

Another less frequent solution is to provide a function and call it on every result:

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

This is less flexible, but arguably faster, than returning a list : lists can be filtered, sorted, stored...


Your question is kind of confusing - you want a function that returns all the values in a list. Well the easiest way of returning a variable number of values is using a list! Are you perhaps trying to emulate Python generators? OCaml doesn't have anything similar to yield, but instead usually accomplishes the same by "passing" a function to the value (using iter, fold or map).

What you have currently written is equivalent to this in Python:

def elements(list):
    if(len(list) == 0):
        return []
    else:
        list[0]
        return elements(list[1:])

If you are trying to do this:

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)

The equivalent in OCaml would be like this:

List.iter dosomething [1;2;3;4;5]

If you are trying to determine if list a is a subset of list b (as I've gathered from your comments), then you can take advantage of List.mem and List.for_all:

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

fun x -> List.mem x b defines a function that returns true if the value x is equal to any element in (is a member of) b. List.for_all takes a function that returns a bool (in our case, the membership function we just defined) and a list. It applies that function to each element in the list. If that function returns true for every value in the list, then for_all returns true.

So what we have done is: for all elements in a, check if they are a member of b. If you are interested in how to write these functions yourself, then I suggest reading the source of list.ml, which (assuming *nix) is probably located in /usr/local/lib/ocaml or /usr/lib/ocaml.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜