views:

70

answers:

2

I'm trying to write a simple recursive function that look over list and return a pair of integer. This is easy to write in c/c++/java but i'm new to ocaml so somehow hard to find out the solution due to type conflict

it should goes like ..

let rec test p l = ... ;;
val separate : (’a -> bool) -> ’a list -> int * int = <fun>
test (fun x -> x mod 2 = 0) [-3; 5; 2; -6];; 
- : int * int = (2, 2)

so the problem is how can i recursively return value on tuple ..

+5  A: 

One problem here is that you are returning two different types: an int for an empty list, or a tuple otherwise. It needs to be one or the other.

Another problem is that you are trying to add 1 to test, but test is a function, not a value. You need to call test on something else for it to return a value, but even then it is supposed to return a tuple, which you can't add to an integer.

I can't figure out what you want the code to do, but if you update your question with that info I can help more.

One guess that I have is that you want to count the positive numbers in the list, in which case you could write it like this:

let rec test l = 
    match l with [] -> 0
   | x::xs -> if x > 0 then 1 + (test xs)
              else test xs;;

Update: since you've edited to clarify the problem, modify the above code as follows:

let test l =
  let rec test_helper l pos nonpos = 
    match l with [] -> (pos, nonpos)
   | x::xs -> if x > 0 then test_helper xs 1+pos, nonpos
              else test_helper xs pos 1+nonpos
  in test_helper l 0 0;;

Using the accumulators help a lot in this case. It also makes the function tail-recursive which is always good practice.

danben
how can i modify it to forward recursive?
REALFREE
I don't think there is any good way to use forward recursion on a list - that would require "growing" your list from `[]` up to the initial input which at best would be extremely inefficient. Also, why did you unaccept my answer? Does it not sufficiently answer your question?
danben
+3  A: 

Been away from OCaml for a bit, but I think this will do the trick in regards to REALFREE's description in the comment

let rec test l = 
  match l with 
      [] -> (0,0) 
    | x::xs -> 
        if x > 0 then match (test xs) with (x,y) -> (x+1, y)
        else  match (test xs) with (x,y) -> (x, y+1);;

You can used the nested match statements to pull out pieces of the tuple to modify

EDIT: I didn't know about the syntax Pascal Cuoq mentioned in his comment below, here's the code like that, it's neater and a little shorter:

let rec test l = 
  match l with 
      [] -> (0,0) 
    | x::xs -> 
    if x > 0 then let (x,y) = test xs in (x+1, y)
    else let (x,y) = test xs in (x, y+1);;

But the accepted answer is still much better, especially with the tail recursion ;).

goggin13
and if you are writing a `match .. with ..` with a single pattern, you can use `let` instead: `let x, y = test xs in ...`
Pascal Cuoq