Kai*_*epi 10 syntax function perl6 raku
可以通过以下几种方式调用函数:
say(1, 2, 3) # 123
say: 1, 2, 3 # (1, 2, 3)
Run Code Online (Sandbox Code Playgroud)
后者似乎通过了Positional,但除此之外,我不知道他们有何不同.是否有任何重要的差异需要知道?你会使用哪种类型的情况?
正如Raiph上面告诉你的那样,say:是一个标签.所以你没有做say任何事情(即使你认为你做过)和 - 在使用REPL之外 - 编译器会抱怨你的使用<a b c>是无用的:
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)?»
Run Code Online (Sandbox Code Playgroud)
但是,您通常可以:在方法调用中使用符号而不是括号.考虑下面的四个例程调用(两个子例程调用然后两个方法调用):
my @numbers = (33, 77, 49, 11, 34);
say map *.is-prime, @numbers ; # simplest subroutine call syntax
say map( *.is-prime, @numbers ); # same meaning, but delimiting args
say @numbers.map( *.is-prime ) ; # similar, but using .map *method*
say @numbers.map: *.is-prime ; # same, but using : instead of parens
Run Code Online (Sandbox Code Playgroud)
这些句子都会返回相同的句子(False False False True False).
一般来说,正如您在上面看到的那样map,您可以()在任何地方使用方法调用:,但相反的情况并非如此; :只能在方法调用中使用.
()如果参数需要精确分隔,请使用,如Raiph在下面评论.
这个答案侧重于基础知识.有关常规调用语法的详细细节的更详尽的报道,请参阅Raiph的答案.(作为一个重要的例子,如果例程名称和冒号(:)或左括号(()之间有任何空格,这些调用的含义通常会改变.
在我开始正确回答之前的一些总体说明:
@jjmerelo的答案涵盖了基础知识.这个补充性的答案,旨在有点详尽,但希望不会耗尽,涵盖陷阱,罕见案例和建议.
我foo: valuea, valueb, ...用来代替方法的名字,foo代表潜艇.
以下所有关于空格/间距的注释忽略了取消间距.
foo:也许令人惊讶的是,这不是一个被称为子的调用say:.
相反,它是一个开始,一个声明标签,<a b c>.
say:您问题中的行不适用于普通程序:
say: <a b c>; # Useless use of constant value a b c ...
Run Code Online (Sandbox Code Playgroud)
"无用"警告意味着say不会以有用的方式使用.该.a-method:不是做与值列表中任何东西.它只是一个没有做任何事情的标签.
大概你正在使用像Perl 6 REPL这样的东西..a-method如果没有使用,REPL会自动成为一行中的最后一个值,从而使该行看起来没有警告.
.如果postfix .a-method: arg2, arg3, ...方法调用没有超出调用者的参数(在左侧.a-method),那么你可以写:
42.say ;
Run Code Online (Sandbox Code Playgroud)
您可以选择附加一个冒号:
42.say: ;
Run Code Online (Sandbox Code Playgroud)
没有充分的理由,但它与以下内容一致:
Numeric如果要为后缀.first: Numeric调用提供一个或多个参数(超出调用者),则必须选择两种方法之一来引入它们.
一种方法是在方法名称之后立即写入冒号,在参数之前,例如;在下面的调用中引入:
say <abc 2 def ghi> .first: Numeric ; # 2
Run Code Online (Sandbox Code Playgroud)
在上面的行中,方法调用表达式在语句终止符处结束.如果有一个封闭的子表达式,如数组下标,则方法调用表达式在该子表达式的末尾结束:
say .[1 + .first: Numeric] given <abc 2 def ghi> ; # ghi
Run Code Online (Sandbox Code Playgroud)
冒号形式方法调用的参数列表也由有效语句修饰符关闭,如given:
say .first: Numeric given <abc 2 def ghi> ; # 2
Run Code Online (Sandbox Code Playgroud)
a-sub arg1, arg2, ...这是子程序调用的相应形式.唯一的格式差异是sub没有调用者或.子名称之前,你必须在子名称后面省略冒号.
.a-method( arg2, arg3, ... )在设计文档中称为"间接对象表示法",这种格式是一种未记录的,很少见的方法调用形式,其中调用者和方法交换位置,中间有空格,没有点:
say 1 + .first(Numeric) given <abc 2 def ghi> ; # 3
Run Code Online (Sandbox Code Playgroud)
a-sub( arg1, arg2, ... )(用于方法和子调用的另一种常见形式是使用parens紧跟方法或子名称 - 必须是立即的,名称和.first- 之间没有任何空格来分隔参数.这是与该&方法一起使用的parens :
say 1 + (.first: Numeric) given <abc 2 def ghi> ; # 3
Run Code Online (Sandbox Code Playgroud)
这样做的优势在于它可以说比使用外壳更可取的更漂亮:
my @array = <abc 2 def ghi> ;
say "first number is &first(Numeric,@array)" ; # first number is 2
Run Code Online (Sandbox Code Playgroud)
如果要将子调用直接放在双引号字符串中,则需要在子名称前加上一个"Some text .a-method()"符号,并使用后缀parens表单:
my @array = <abc 2 def ghi> ;
say "first number is @array.first(Numeric)" ; # first number is 2
Run Code Online (Sandbox Code Playgroud)
同样,要进行方法调用,您必须再次使用postfix parens表单:
my @array = <abc 2 def ghi> ;
say "no method call @array[3].uc" ; # no method call ghi.uc
say "with method call @array[3].uc()" ; # with method call GHI
say "&rand"; # &rand
say "&rand()"; # 0.929123203371282
Run Code Online (Sandbox Code Playgroud)
如果没有参数(超出方法调用的调用范围),如果要在字符串中插入子或方法调用,则仍需要将此表单与空的parens一起使用:
This type (QAST::WVal) does not support positional operations
Run Code Online (Sandbox Code Playgroud)
.a-method ( arrgh, arrgh, ... ) ;这不行.
因为.a-method后面没有冒号,所以方法调用被认为是完整的.
这意味着下一件事必须是表达式/语句ender ;,或者是对方法调用结果进行操作的后缀运算符,或者是对结果和后续参数进行操作的中缀运算符.
但( arrgh, arrgh, ... )这些都不是.所以你得到一个"连续两个术语"的编译错误.
.a-method:( arrgh, arrgh, ... ) ;.a-method: ( arrgh, arrgh, ... ) ;:作为方法调用的一部分,请勿混淆使用a 作为参数的parens.
在冒号和打开paren之间没有空格的情况下这样做会产生一个神秘的编译错误:
say .first: (Numeric) given <abc 2 def ghi> ; # 2
Run Code Online (Sandbox Code Playgroud)
留出空间似乎有效 - 但通常只有运气:
say .first: Numeric given <abc 2 def ghi> ; # 2
Run Code Online (Sandbox Code Playgroud)
这(Numeric)是parens中的单个值,Numeric因此该行与以下相同:
say .first: Numeric, :k given <abc 2 def ghi> ; # 1
say .first(Numeric, :k) given <abc 2 def ghi> ; # 1
Run Code Online (Sandbox Code Playgroud)
但如果在parens中有两个或更多的争论,事情就会出错.使用以下形式之一:
say .first: (Numeric, :k) given <abc 2 def ghi> ; # Nil
Run Code Online (Sandbox Code Playgroud)
这正确地产生2元素的数组索引("key")而不是:
invocant.a-method(( valuea, valueb, ... ));
Run Code Online (Sandbox Code Playgroud)
产生的Nil原因是该.first方法对单个参数(表单列表)没有任何用处(Numeric, :k).
当然,您可能偶尔想要传递一个参数,该参数是parens中的值列表.但你仍然不能使用冒号.为了清楚起见,我建议您将其写为:
`a-sub( valuea, valueb, ... ) ;`
Run Code Online (Sandbox Code Playgroud)
a-sub ( arrgh1, arrgh2, ... ) ;正如刚才为方法调用所解释的那样,它传递了一个参数a-sub,即单个列表( arrgh1, arrgh2, ... ),它很少是作者的意思.
同样,我的建议是将其写为:
`a-sub valuea, valueb, ... ;`
Run Code Online (Sandbox Code Playgroud)
要么:
`a-sub(( valuea, valueb, ... )) ;`
Run Code Online (Sandbox Code Playgroud)
如果您要传递多个参数,或者如果您希望将列表作为单个参数传递,则:
qux.&a-sub
Run Code Online (Sandbox Code Playgroud)
.a-method : arrgha, arrghb, ...a-sub : arrgha, arrghb, ...对于方法表单,这将为您提供"混淆"编译错误.
如果a-sub不带参数,子表单也是如此.如果a-sub接受参数,你会得到一个"Preceding context需要一个术语,但是找到了infix:而不是"编译错误.
.&a-sub最后,有一个调用表单,它允许您使用.method调用语法调用声明为sub的例程.以下提供qux点左侧的"invocant" 作为子的第一个参数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
Run Code Online (Sandbox Code Playgroud)
:像往常一样使用或括号将其他参数传递给a-sub:
say first <abc 2 def ghi>: Numeric ; # 2
Run Code Online (Sandbox Code Playgroud)
(在我的这一部分的原始版本中,我写道,人们不能传递额外的论点.我已经测试了这个并且认为不可能.但我必须对某些东西感到困惑.@ Enheh的评论让我重新测试并发现一个人可以像普通方法调用一样传递其他参数.谢谢@Enheh.:))