首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >什么时候可以调用没有标签的带标签参数的函数?

什么时候可以调用没有标签的带标签参数的函数?
EN

Stack Overflow用户
提问于 2019-10-10 04:51:45
回答 2查看 408关注 0票数 2

似乎在某些情况下,如果函数的顺序是正确的,就可以使用带标签的参数调用函数。

代码语言:javascript
运行
复制
let f ~x ~y = Format.sprintf "%d %s" x y;;
f 3 "test";;

成功地运行,但是

代码语言:javascript
运行
复制
f "test" 3;;

错误消息失败。

代码语言:javascript
运行
复制
Line 1, characters 2-8:
Error: This expression has type string but an expression was expected of type
         int

对于带有可选参数的函数,如果不传递可选参数,它似乎可以工作:

代码语言:javascript
运行
复制
let f ?(x = 1) ~y () = Format.sprintf "%d %s" x y;;
f "help" ();;

成功了,但是

代码语言:javascript
运行
复制
f 2 "help" ();;

错误消息失败。

代码语言:javascript
运行
复制
Line 1, characters 4-10:
Error: The function applied to this argument has type
         ?x:int -> y:string -> string
This argument cannot be applied without label

在可能的情况下,是否有一条一般规则?

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2019-10-10 13:07:00

如果应用程序是总计(即提供了所有必需的参数),如果函数的返回类型不是类型变量,则可以省略标签。可选参数的参数必须始终由标签传递。

我们来举几个例子,

代码语言:javascript
运行
复制
let example1 ?(opt=0) ~a ~b ~c unlabeled = 
  opt + a + b + c + unlabeled;;

example1 1 2 3 4;;
- : int = 10

在这里,我们能够在没有标签的情况下应用所有参数,因为我们提供了所有必需的参数(不需要可选参数,因此不需要名称),并且结果类型不是多态的。但是,如果我们将List.fold函数从Core或ListLabels中取出来,那么它的类型是

代码语言:javascript
运行
复制
'a list -> init:'accum -> f:('accum -> 'a -> 'accum) -> 'accum

然后我们会得到,

代码语言:javascript
运行
复制
List.fold [1;2;3;4] 0 (+);;
- : init:(int -> (int -> int -> int) -> '_weak1) ->
    f:((int -> (int -> int -> int) -> '_weak1) ->
       int -> int -> (int -> int -> int) -> '_weak1) ->
    '_weak1

而不是10,这是人们所期望的。原因是因为生成的类型'accum是一个类型变量,所以它也可以是一个函数,例如,int -> intstring -> int -> unit等等--所有这些类型都与'accum类型匹配。这基本上意味着这个函数接受可能无限数量的位置参数。因此,我们提供的所有参数都被解释为位置,因此,我们永远无法填写标记的参数,因此,我们的应用程序没有被总计。这实际上使我们在投递开始时对规则的原始定义变得多余--因为一个应用程序(它的类型由类型变量表示)永远不可能是总计的。

请注意,只有当返回类型是类型变量时才会出现此问题,而不只是包含一些类型变量,例如,我们可以很容易地省略带有List.map函数的标签,例如,给定具有类型的List.map

代码语言:javascript
运行
复制
'a list -> f:('a -> 'b) -> 'b list

我们可以很容易地应用它。

代码语言:javascript
运行
复制
# List.map [1;2;3] ident;;
- : int Core_kernel.List.t = [1; 2; 3]

尽管如此,人们通常认为省略标签是一种错误的做法。主要是因为多态返回类型的警告,并因为它使得标记参数的顺序很重要,这有点违背直觉。

票数 4
EN

Stack Overflow用户

发布于 2019-10-10 08:23:56

是的,这是有一般规则的。来自手册

形式参数和参数根据各自的标签进行匹配,没有标签被解释为空标签。这允许在应用程序中交换参数。还可以对任何参数部分应用一个函数,为其余参数创建一个新函数。 如果一个函数的几个参数都带有相同的标签(或没有标签),它们之间就不会通勤,而顺序就会起作用。但他们仍然可以与其他论点通勤。 作为上述参数匹配规则的一个例外,如果应用程序为(省略所有可选参数),则可以省略标签。在实践中,许多应用程序都是总计的,因此通常可以省略标签。

票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/58315641

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档