Function 什么';这两种函数调用约定的区别是什么?

Function 什么';这两种函数调用约定的区别是什么?,function,syntax,raku,Function,Syntax,Raku,函数可以通过以下几种方式调用: say(1, 2, 3) # 123 say: 1, 2, 3 # (1, 2, 3) 后者似乎通过了一个位置,但除此之外,我不知道它们还有什么不同。是否有重要的差异需要了解?你会在哪种情况下使用一种而不是另一种?正如Raiph在上面告诉你的,说:是一个标签。因此,您没有说任何话(即使您认为您说了),而且——在REPL的使用之外——编译器会抱怨您使用的是无用的: say: <a b c>; # OUTPUT: «WARNINGS for <tm

函数可以通过以下几种方式调用:

say(1, 2, 3) # 123
say: 1, 2, 3 # (1, 2, 3)

后者似乎通过了一个
位置
,但除此之外,我不知道它们还有什么不同。是否有重要的差异需要了解?你会在哪种情况下使用一种而不是另一种?

正如Raiph在上面告诉你的,
说:
是一个标签。因此,您没有说任何话(即使您认为您说了),而且——在REPL的使用之外——编译器会抱怨您使用的
是无用的:

say: <a b c>; # OUTPUT: «WARNINGS for <tmp>:␤Useless use of constant value a b c in sink context (lines 1, 1, 1, 1, 1, 1)␤»
这些句子都将返回相同的
(False-False)

一般来说,正如上面使用
map
所看到的,您可以在方法调用中使用
()
,无论您在哪里使用
,但情况并非相反<代码>:只能在方法调用中使用

如果参数需要精确分隔,请使用
()
,如下面的Raiph注释所示


这个答案集中在基础上。有关例程调用语法的详细信息,请参见Raiph的答案。(作为一个重要的例子,如果例程名称和冒号(
)或左括号(
)之间有空格,则这些调用的含义通常会改变。)@jjmerelo的答案涵盖了基础知识。这一补充答案旨在尽可能详尽,但希望不会穷尽,涵盖陷阱、罕见案例和建议

foo:valuea,valueb,…
令人惊讶的是,这不是对名为
foo
的子方法或方法的调用

相反,它是一个以,
foo:
开头的语句

问题中的
说:
行在普通程序中不起作用:

say: <a b c>; # Useless use of constant value a b c ...
您可以选择附加冒号:

42.say: ;
没有充分的理由这样做,但这与:

.a-method:arg2、arg3、…
如果要为后缀
.a-method
调用提供一个或多个参数(invocant除外),则必须从两种方法中选择一种引入它们

一种方法是在方法名之后、参数之前写一个冒号。方法名和冒号之间不能有空格,方法参数之前的冒号后面必须有空格。1

例如,以下方法调用中的
Numeric
参数前使用冒号:

say <abc 2 def ghi> .first: Numeric ; # 2
冒号形式方法调用的参数列表也会被有效的like
GIVENT
关闭:

say .first: Numeric given <abc 2 def ghi> ; # 2
这有一个优点,可以说它比使用外部paren的替代方案更漂亮:

say 1 + (.first: Numeric) given <abc 2 def ghi> ; # 3
要进行方法调用,您必须再次使用后缀parens表单,并且还必须提供显式invocant(您不能只编写
“一些text.a-method()”
):

留下一个空间似乎是可行的——但通常只有靠运气:

say .first: (Numeric) given <abc 2 def ghi> ; # 2
但是,如果parens中有两个或多个参数,则会出现问题。请使用以下形式之一:

say .first: Numeric, :k given <abc 2 def ghi> ; # 1
say .first(Numeric, :k) given <abc 2 def ghi> ; # 1
这会产生
Nil
,因为
.first
方法对一个参数没有任何用处,该参数是
(数值,:k)
形式的列表

当然,您可能偶尔希望传递一个参数,该参数是parens中的值列表。但是您可以不使用冒号来传递。为了清楚起见,我建议您将其写成:

invocant.a-method(( valuea, valueb, ... ));
`a-sub( valuea, valueb, ... ) ;`
a-sub(arrgh1,arrgh2,…);
正如刚才对方法调用所解释的,这会将一个参数传递给
a-sub
,即单个列表
(arrgh1,arrgh2,…)
,这很少是编写器的意思

同样,我的建议是改为这样写:

invocant.a-method(( valuea, valueb, ... ));
`a-sub( valuea, valueb, ... ) ;`
或:

如果要传递多个参数,或者希望将列表作为单个参数传递,则:

`a-sub(( valuea, valueb, ... )) ;`
.a-方法:arrgha,arrghb,
a-sub:arrgha,arrghb,…
对于方法表单,这将导致“混乱”的编译错误

如果
a-sub
不带参数,则子表单也是如此。如果
a-sub
带参数,则会出现“前面的上下文需要一个术语,但找到了中缀:而是”编译错误

&a-sub
有一个调用表单,允许您调用声明为sub的例程,但使用
.method
调用语法。以下内容将点左侧的“invocant”
qux
作为名为
a-sub
的sub的第一个参数提供:

qux.&a-sub
sub a-sub ($a, $b) { $a == $b }
say 42.&a-sub(42), 42.&a-sub(43); # TrueFalse
say 42.&a-sub: 42;                # True
像往常一样使用
或括号将附加参数传递给
a-sub

qux.&a-sub
sub a-sub ($a, $b) { $a == $b }
say 42.&a-sub(42), 42.&a-sub(43); # TrueFalse
say 42.&a-sub: 42;                # True
(在本节的原始版本中,我写道一个人不能传递额外的参数。我已经测试过了,并且认为一个人不能传递。但我一定是被什么东西弄糊涂了。@Enheh的评论让我重新测试,发现一个人可以像传递普通方法调用一样传递额外的参数。谢谢@Enheh.)

a-方法(发票人:arg2、arg3等)
a-方法发票:arg2,arg3,…
这些格式在设计文档中称为“间接对象表示法”,是一种未记录且很少见到的方法调用形式,在这种形式中,调用模仿方法声明——方法名称先出现,发票后是冒号:

say first <abc 2 def ghi>: Numeric ; # 2

先说。

说:
是一个标签,不是函数调用。如果您编写
I'm-a-label:1、2、3
,应该会得到相同的结果。我猜您使用的是REPL,如果您不使用
say
,它会显示输入表达式的值。哦,我不知道。为什么它会起作用呢?它不起作用。如果您将两个版本分别放在各自的文件中并运行它们,则
说(1,2,3)
打印出“123”,而另一个则不执行任何操作。Perl抱怨常量整数的无用使用。当然,在REPL中,每个表达式的结果都会被打印出来,所以它不再是无用的了
invocant.a-method(( valuea, valueb, ... ));
`a-sub( valuea, valueb, ... ) ;`
`a-sub  valuea, valueb, ...   ;`
`a-sub(( valuea, valueb, ... )) ;`
qux.&a-sub
sub a-sub ($a, $b) { $a == $b }
say 42.&a-sub(42), 42.&a-sub(43); # TrueFalse
say 42.&a-sub: 42;                # True
say first <abc 2 def ghi>: Numeric ; # 2