Search code examples
listrecursionfunctional-programmingocaml

Trying to get the number of even and odd integers in a list


I am trying to write a recursive function that takes in a list as argument and returns the number of even and odd numbers in tuple (number_of_even, number_of_odd)

let rec countEvenOdd lst e o =
  match lst with
  | [] -> (e,o) (* Base case: empty list *)
  | hd :: tl -> if hd mod 2 = 0 then countEvenOdd tl (e + 1) o else countEvenOdd tl e (o + 1)
;;

countEvenOdd [2;4;5;6;7;8];;

This just gives me the type:

- : int -> int -> int * int = <fun>

Solution

  • Because you've provided one argument to a function which expects three, you have partially applied the function, so you get a function back which takes the remaining two arguments.

    This is a crucial elementary aspect of programming in OCaml: functions take one argument and return one value. That value returned may be a function itself.

    In your specific case doubtless you meant to call countEvenOdd [2; 4; 5; 6; 7; 8] 0 0 but you can hide that implementation detail by shadowing countEvenOdd.

    let rec countEvenOdd lst e o =
      match lst with
      | [] -> (e,o) (* Base case: empty list *)
      | hd :: tl -> 
        if hd mod 2 = 0 then countEvenOdd tl (e + 1) o 
        else countEvenOdd tl e (o + 1)
    
    let countEvenOdd lst = countEvenOdd lst 0 0
    

    Note, you might just make the accumulator a tuple rather than two arguments.

    let rec countEvenOdd lst (e, o as acc) =
      match lst with
      | [] -> acc
      | hd :: tl -> 
        if hd mod 2 = 0 then countEvenOdd tl (e + 1, o) 
        else countEvenOdd tl (e, o + 1)
    

    Of course, this starts to look like a fold.

    let countEvenOdd lst =
      List.fold_left 
        (fun (e, o) x -> if x mod 2 = 0 then (e+1, o) else (e, o+1)) 
        (0, 0) 
        lst