Istvan
Istvan

Reputation: 8552

What is the right way of defining a multiple arity function in OCaml?

I am trying to implement a simple range function in OCaml and I was wondering how can i do that for different arity calls.

let range_aux ~start  ~stop  ~step  =
  let rec aux start stop step acc =
    match (start, stop, step, acc) with
    | (start,stop,step,acc) when start = stop -> List.rev acc
    | (start,stop,step,acc) -> aux (start + step) stop step (start :: acc) in
  aux start stop step []

let range ~start ~stop  ~step  = range_aux ~start ~stop ~step
let range ~stop  ~step  = range_aux ~start:0 ~stop ~step
let range ~stop  = range_aux ~start:0 ~stop ~step:1

This obviously does not work the last definition wins. Is there a way to define multiple arity functions?

Upvotes: 4

Views: 258

Answers (1)

octachron
octachron

Reputation: 18892

Overloading of function does not exist in OCaml in general. For your specific use case, it is possible to use optional arguments:

let range ?(start=0) ?(step=1) stop = range_aux ~start ~step ~stop
let a = range 2
let b = range ~start:1 2
let c = range ~start:1 ~step:2 5

where ?(start=0) means that the named argument start is optional and its default value is 0.

Note that I made stop a positional argument since the compiler needs a least one positional argument to know when to consume optional arguments. Another possibility would have been to add an unit argument as a last argument:

let range ?(start=0) ?(step=1) ~stop () = range_aux ~start ~step ~stop
let a = range ~stop:2 ()

p.s. your range_aux will descend into an infinite recursion when start > stop or (stop - start) mod step ≠ 0.

Upvotes: 6

Related Questions