在OCaml中,与函数的多个参数匹配的规范方法是什么?

Pte*_*mys 9 ocaml pattern-matching

您可以通过创建元组然后在匹配表达式中对其进行解构来对函数的多个参数进行模式匹配:

let f x y =
  match x, y with
  | pattern1 -> expr1
  | ...
Run Code Online (Sandbox Code Playgroud)

或者,如果你不需要curried函数,你可以通过f将一个元组作为唯一参数来实现:

let f (x, y) = function
  | pattern1 -> expr1
  | ...
Run Code Online (Sandbox Code Playgroud)

后一种方法的优点是每次定义函数时都不必编写两次参数.但是采用元组的函数似乎并不像curry那样受欢迎.

那么在OCaml社区中哪两个被认为是规范的或者首选的?

编辑:正如下面指出的垫,我的意思是let f = function blah blah在第二个代码片段.

Mar*_*bon 11

这个解决方案是规范的:

let f x y =
  match x, y with
  | pattern1 -> expr1
  | ...
Run Code Online (Sandbox Code Playgroud)

编译器优化了这种特殊情况,并没有为元组实际分配块(x, y).


Chr*_*way 9

元组不仅仅是一个语法结构,它代表了一个真实的数据结构.这意味着fun (x,y)(非常轻微)效率低于f x y情况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
Run Code Online (Sandbox Code Playgroud)

因此,除非您有充分的理由这样做,否则通常最好避免使用元组作为函数参数.

PS类似的考虑适用于数据类型声明,其中以下是微妙的不同:

type 'a foo = Foo of 'a * 'a;
type 'a bar = Bar of ('a * 'a);
Run Code Online (Sandbox Code Playgroud)

Foo是一个带有两个参数的数据类型构造函数.Bar是一个带有一个参数(一个元组)的构造函数.


pad*_*pad 5

实际上,f = function...是这样的捷径f (x, y) = match (x, y) with...:

let f = function 
  | pattern1_of_x_y -> expr1
  | ...
Run Code Online (Sandbox Code Playgroud)

是相同的:

let f (x, y) =
  match x, y with
  | pattern1 -> expr1
  | ...
Run Code Online (Sandbox Code Playgroud)

(请注意,您的第二个配方中存在错误;这两个版本不兼容).

正如您所指出的那样,人们无法避免使用match ... with...curry函数.就个人而言,我更喜欢功能的curry形式,因为它更灵活,特别是部分应用.而且,模式匹配不仅应用于函数参数; 它们在OCaml中基本上被使用,这使得match ... with...构造变得更加重要.

每当您发现上述使用模式时,请尝试替换match ... with...function.这只是一种风格问题,所以这里没有更多的选择.