2011-11-27 9 views
7

あなたはタプルを作成し、一致式でそれを構造化代入することにより、関数の複数の引数に対してパターンマッチでした:あなたはカリー化機能を必要としない場合、あなたはこのことで操作を行うことができ、OCamlでは、関数の複数の引数に対してマッチングする正規の方法は何ですか?

let f x y = 
    match x, y with 
    | pattern1 -> expr1 
    | ... 

またfを作ることは唯一の引数としてタプルを取る:

let f (x, y) = function 
    | pattern1 -> expr1 
    | ... 

後者の方法の利点は、あなたが二回あなたが関数を定義するたびに、引数を記述する必要はありませんということです。しかし、タプルを取る関数は、カドゥンよりも一般的ではないようです。

OCamlコミュニティでは、2つのうちどちらが正準であると思われますか?

EDIT:下記のパッドのように、2番目のコードスニペットではlet f = function blah blahを意味します。

答えて

8

タプルは単なる構文構造ではなく、実際のデータ構造を表します。これは、タプルが割り当てられなければならないので、xyがまだタプルされていない場合、fun (x,y)f x yよりも(非常にわずかに)効率が低いことを意味します。これが明確でない場合は、Javaでラフ相当するものは、それはあなたがそうする正当な理由がない限り、関数の引数としてタプルを使用しないように、一般的に望ましいですが、そのため

void foo(X x, Y y) { ... } 
void bar(Tuple<X,Y> t) { ... } 

/* client code */ 
X x = new X(); 
Y y = new Y(); 

foo(x, y); // Just uses x and y directly 
bar(new Tuple<X,Y>(x, y)); // Has to "new" a Tuple 

だろう。

P.S.同様の考慮事項は、次のように微妙に異なるデータ型の宣言に適用されます。

type 'a foo = Foo of 'a * 'a; 
type 'a bar = Bar of ('a * 'a); 

Fooは2つの引数を取るデータ型コンストラクタです。 Barは、1つの引数(タプル)を受け取るコンストラクタです。

4

実際、f = function...そうf (x, y) = match (x, y) with...のショートカットである:

let f = function 
    | pattern1_of_x_y -> expr1 
    | ... 

は同じである:

let f (x, y) = 
    match x, y with 
    | pattern1 -> expr1 
    | ... 

(2番目の製剤中の間違いがあることに注意してください。これらの2つのバージョンがありません互換性あり)。

あなたが指摘したように、match ... with...をカルト機能で使用することは避けられません。個人的には、特に部分的なアプリケーションでは、柔軟性が高いので、私は関数のカレー化された形式を好みます。さらに、パターンマッチングは関数の引数に適用されるだけでなく、本質的にOCamlのどこでも使用されているため、match ... with...の構築がさらに重要になります。

上記のように使用パターンを見つけたら、match ... with...functionに置き換えてみてください。それは単なるスタイルの問題なので、ここでは何も好まれません。

8

この溶液を正規である:

let f x y = 
    match x, y with 
    | pattern1 -> expr1 
    | ... 

コンパイラは、この特殊なケースを最適化し、実際のタプル(x, y)ブロックを割り当てません。

3

標準的な方法は、カレー化された関数であり、タプル上のmatch、つまり最初のスニペットです。

これは、標準ライブラリの書き方です(標準ライブラリのソースを参照してください。例えば、多くの機能はlist.mlです)。

これは、実装が特にネイティブコードコンパイラに最適化される方法でもあります。タプルや他のブロックを作成し、それがブロックを必要とする関数に渡さずにすぐに破棄すると、ネイティブコードコンパイラはそれを見つけて、ブロックの割り当てを避けることがよくあります。ブロックを割り当てることになっても、ブロックがマイナーヒープとプロセッサキャッシュに残る可能性を高めるために、ブロックの持続時間をできるだけ短くする方が効率的です。

関連する問題