Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Keeping a counter at each recursive call in OCaml

I am trying to write a function that returns the index of the passed value v in a given list x; -1 if not found. My attempt at the solution:

let rec index (x, v) =
    let i = 0 in
        match x with
        [] -> -1
        | (curr::rest) -> if(curr == v) then
                            i
                          else
                            succ i; (* i++ *)
                            index(rest, v)
;;

This is obviously wrong to me (it will return -1 every time) because it redefines i at each pass. I have some obscure ways of doing it with separate functions in my head, none which I can write down at the moment. I know this is a common pattern in all programming, so my question is, what's the best way to do this in OCaml?

like image 816
id2341677 Avatar asked Dec 09 '22 01:12

id2341677


2 Answers

Mutation is not a common way to solve problems in OCaml. For this task, you should use recursion and accumulate results by changing the index i on certain conditions:

let index(x, v) =
    let rec loop x i =
        match x with
        | [] -> -1
        | h::t when h = v -> i
        | _::t -> loop t (i+1)
    in loop x 0

Another thing is that using -1 as an exceptional case is not a good idea. You may forget this assumption somewhere and treat it as other indices. In OCaml, it's better to treat this exception using option type so the compiler forces you to take care of None every time:

let index(x, v) =
    let rec loop x i =
        match x with
        | [] -> None
        | h::t when h = v -> Some i
        | _::t -> loop t (i+1)
    in loop x 0
like image 69
pad Avatar answered Dec 11 '22 13:12

pad


This is pretty clearly a homework problem, so I'll just make two comments.

First, values like i are immutable in OCaml. Their values don't change. So succ i doesn't do what your comment says. It doesn't change the value of i. It just returns a value that's one bigger than i. It's equivalent to i + 1, not to i++.

Second the essence of recursion is to imagine how you would solve the problem if you already had a function that solves the problem! The only trick is that you're only allowed to pass this other function a smaller version of the problem. In your case, a smaller version of the problem is one where the list is shorter.

like image 45
Jeffrey Scofield Avatar answered Dec 11 '22 15:12

Jeffrey Scofield