首页 > 解决方案 > 最后的可选参数影响之前的标签参数

问题描述

为什么let f ~x ?(y = 1) = x - y;;让参数的标签x变得必要?换句话说,当我尝试评估时f 3 ~y:2;;,我收到了这个错误:

Error: The function applied to this argument has type x:int -> int
This argument cannot be applied without label

这种设计背后的原因是什么?

标签: ocaml

解决方案


不必标记参数 x:

let g = f 0

工作并返回一个g类型的函数?y:int -> int

要理解这种行为,最好记住通用规则是在应用函数时标签是强制性的。

但是,完全应用有一个特定规则:如果将函数应用于尽可能多的非可选参数,则可以省略标签。

一个典型的例子是

let f ~a ~b c d ~e f ~g = a + b + c + d + e + f + g
let x = f 1 2 3 4 5 6 7  

回到您的案例,您的函数f最多接受一个非可选参数。因此,当仅应用于一个论点时,它被认为是完全应用的。

另一个重要的一点是,可选参数仅在发送后续位置参数后才发送到函数。这解释了为什么变量g仍然是一个函数:没有提供位置参数,f因此可选参数?y从未发送到f.

应用于更复杂的例子

let f ~a ?(b=0) c ~d e ~f ~g ?(h=0) = a + b + c + d +e + f + g + h 
 (* there are 8 arguments, 2 optional *)
 (* g is applied to the full 6 non-optional arguments, thus total *)
let g = f 1 3 4 5 6 7

的类型g?h:int -> 0。实际上,该应用程序是完整的,因此已提供所有非可选参数。然后,第一个可选参数?b后跟一个位置参数。然后将其提供给函数。但是,最后一个可选参数?h还没有被触发,仍然在这里。

这种行为意味着可选参数只有在它们之后至少有一个位置参数时才有用,正如编译器本身所建议的那样:

let f ~x ?(y=0) = x + y;;
Line 1, characters 11-14:
Warning 16: this optional argument cannot be erased.

推荐阅读