In OCaml, what is the canonical way to map to multiple function arguments?

You can match patterns with multiple function arguments by creating a tuple and then destroying it in the match expression:

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

Alternatively, if you do not need the curried function, you can do this by doing f to take the tuple as the only argument:

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

The advantage of the latter method is that you do not need to write arguments twice each time you define a function. But the functions that take the tuple do not seem to be as popular as the curry.

So, which of the two is considered canonical or preferred in the OCaml community?

EDIT: Like the pointer below, I mean let f = function blah blah in the second code snippet.

+7
source share
4 answers

A tuple is not just a syntactic construct, it is a real data structure. This means that fun (x,y) (very slightly) less efficient than fxy if x and y are not already loaded because a tuple must be assigned. If this is not clear, the rough equivalent in Java will be

 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 

For this reason, it is usually preferable to avoid using tuples as arguments to the function unless you have a good reason for doing so.

PS A similar consideration applies to data type declarations, where the following are slightly different:

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

Foo is a data type constructor that takes two arguments. Bar is a constructor that takes one argument (tuple).

+8
source

This solution is canonical:

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

The compiler optimizes this special case and does not actually allocate a block for the tuple (x, y) .

+8
source

Actually, f = function... is a shortcut to f (x, y) = match (x, y) with... , therefore:

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

matches with:

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

(Note that there is a mistake in the second wording, these two versions are incompatible).

As you pointed out, you cannot use match ... with... in a curry function. Personally, I prefer the currency form of the function, since it is more flexible, especially with partial use. Moreover, pattern matching is used not only in function arguments; they are used almost everywhere in OCaml, which makes the match ... with... construct even more important.

Whenever you specify a usage pattern as above, try replacing match ... with... with function . It's just a matter of style, so there is nothing more preferable here.

+4
source

The canonical way is a curry function and match on a tuple, i.e. your first snippet.

This is how the standard library is written (see standard library sources, for example, many functions in list.ml ).

It is also a way to optimize implementation, especially your own code compiler. If you create a tuple or other block and immediately destroy it without passing it to functions waiting for the block, the native code compiler often points out this and avoids allocating the whole block. Even if you end up allocating a block, it is more efficient to make the block duration as short as possible in order to increase the likelihood that the block will remain in a small heap and in the processor cache.

+3
source

All Articles