functional-programmingcomparepattern-matchingocamlindexoutofboundsexception

Comparison in pattern matching in OCaml


I want to write a function set which changes the index i in the 'a array a to the value 'a v and raise an invalid_argument exception if i is bigger then the length-1 of the array. I know that this can be done with if/then/else:

let set i v a = 
  let l = Array.length a in 
  if i > (l-1) then 
    raise (Invalid_argument "index out of bounds")
  else 
    a.(i) <- v

However I want to know if this can be achieved in a pure functional approach, using pattern matching and the OCaml standard library. I don't how to compare values inside the pattern matching, I get an error at the marked line:

let set i v a = 
  let l = Array.length a in
  match i with 
 >>>>>>  | > l-1 -> raise (Invalid_argument "index out of bounds")
         | _ -> a.(i) <- v

Is there a workaround to achieve this? perhaps with a helper function?


Solution

  • An if expression is a pure functional approach, and is also the right approach. In general, pattern matching has the purpose of deconstructing values; it's not an alternative to an if.

    However, it's still possible to do this with pattern matching:

    let set i v a =
       let l = Array.length a in
       match compare l i with
       | 1 -> a.(i) <- v
       | _ -> raise @@ Invalid_argument "index out of bounds"
    

    EDIT: Apparently, compare can return other values than -1, 0 and 1 so this version is not reliable (but you wouldn't use it anyway, would you?)...

    Or, more efficiently

    let set i v a =
       let l = Array.length a in
       match l > i with
       | true -> a.(i) <- v
       | false -> raise @@ Invalid_argument "index out of bounds"
    

    But then you realize that matching over a boolean is just an if. Which is why the correct version is still

    let set i v a =
       let l = Array.length a in
       if l > i then a.(i) <- v
       else raise @@ Invalid_argument "index out of bounds"