考虑这些只接受一个命名参数的子程序。命名参数应该是可选的,我没有看到任何例外。
如果没有类型约束,那么没有问题; 命名参数不是必需的。如果有可以接受类型对象的类型约束(没有注释,:U
和:_
),那也不会存在问题。
Parameter '$quux' of routine 'quux' must be an object instance of type 'Int',
not a type object of type 'Int'. Did you forget a '.new'?
in sub quux at /Users/brian/Desktop/type.p6 line 16
in block <unit> at /Users/brian/Desktop/type.p6 line 37
如果使用注释:D
来设置需要一个定义的值的类型约束,那么该命名参数就不再是可选的。也就是说,在其他定义中,我不必提供值。但是使用:D
时,我必须提供一个值。我宁愿不要省略:D
,因为我想要的值必须被定义。
从Signatures文档中可以得到:
通常,类型约束只检查传递的值是否为正确的类型。
但是,在这里我没有传递任何值。我认为这些约束只适用于赋值操作。由于我没有显式地提供要分配的值,所以我认为不会有任何赋值和问题。然而,在Rakudo 2017.10中并非如此。这导致我采取各种不良方式进行解决。这与我的问题“对于Perl 6块而言,那是一个参数还是零个?”有关,我试图区分零个和一个参数的情况。
我可以通过分配默认值来解决这个问题,但在某些情况下,没有任何有意义的默认值。例如,Bool
很容易,但是什么确切的Int
适合呢?无论它是什么,都将成为一些魔法值,这会使代码变得复杂和混乱。我用“Perl 6是否有无限整数”来解决这个问题,但我之所以能够这样做是因为Inf
在这种情况下可以作为有效的值。
sub foo ( :$foo ) {
put $foo.defined ?? 'foo defined' !! 'foo not defined';
}
sub bar ( Int :$bar ) {
put $bar.defined ?? 'bar defined' !! 'bar not defined';
}
sub baz ( Int:U :$baz ) {
put $baz.defined ?? 'baz defined' !! 'baz not defined';
}
sub quux ( Int:D :$quux ) {
put $quux.defined ?? 'quux defined' !! 'quux not defined';
}
sub quack ( Int:_ :$quack ) {
put $quack.defined ?? 'quack defined' !! 'quack not defined';
}
foo();
foo( foo => 2 );
bar();
bar( bar => 2 );
baz();
baz( baz => Int );
quack();
quack( quack => 2 );
quux( quux => 2 );
quux();