2017-10-22 7 views
4

私はOCamlで単純な範囲関数を実装しようとしています。OCamlで複数のアーリー関数を定義する正しい方法は何ですか?

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 

これは明らかに最後の定義がうまくいきません。複数のアーリー関数を定義する方法はありますか?

+2

しないでください。オプションの引数を使用する –

答えて

6

一般にOCamlに関数のオーバーロードが存在しません。

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 

?(start=0)は、名前付き引数startはオプションで、デフォルト値は0であることを意味します。あなたの特定のユースケースの場合は、オプションの引数を使用することが可能です。

stopは、コンパイラがオプションの引数をいつ消費するかを知るために、少なくとも1つの位置引数を必要とすることに注意してください。

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

P.S.: 別の可能性は、最後の引数としてユニット引数を追加することであっただろうは、start > stopまたは(stop - start) mod step ≠ 0の場合、無限再帰になります。

関連する問題