这有点意外的行为,可能会咬人初学者。首先,这是打算吗?其次,Perl 6使用什么来猜测要创建哪个对象?它是否开始认为它是Block或Hash并稍后更改,还是最终决定?
你可以构建一个带括号和胖箭头的Hash:
my $color-name-to-rgb = {
'red' => 'FF0000',
};
put $color-name-to-rgb.^name; # Hash
使用另一个Pair符号也会创建一个Hash。
my $color-name-to-rgb = {
:red('FF0000'),
};
但是,没有胖箭,我得到一个Block代替:
my $color-name-to-rgb = {
'red', 'FF0000',
};
put $color-name-to-rgb.^name; # Block
还有其他方法来定义哈希,但我问的是这个特定的语法,而不是寻找我已经知道的解决方法。
$ perl6 -v
This is Rakudo version 2017.04.3 built on MoarVM version 2017.04-53-g66c6dda
implementing Perl 6.c.
首选的Perl6方法是使用%( )
创建哈希。
my $color-name-to-rgb = %(
'red', 'FF0000',
);
我不建议人们使用大括号来创建哈希。如果他们想要制作哈希,那么%( )
就是这样做的正确方法。
如果你来自Perl 5世界,最好养成在创建哈希时使用%( )
而不是{ }
的习惯。
TL; DR这个答案从我认为合理的最简单的描述开始,然后尝试以精确的细节覆盖所有内容。如果有任何问题太复杂或缺失,请在评论中告诉我。
只有术语position1中的支撑代码({...}
)才能使用此DWIM / WAT.2
在这些例子中,{...}
不是术语位置:
if True { ... } # always a block
class foo { ... } # always a package
put bar{ ... } # always a hash index
对于本答案的其余部分,{...}
仅表示术语位置的支撑代码。
{...}
in term position{...}
是Block
。此外,如果它有签名,多个语句或标识符的声明,那么它就是Block
。{...}
只包含零个或多个值的列表,直接从%
sigil'd变量(例如%foo
)或Pair
文字(例如:bar
)开始,那么它就是Hash
。Block
一些支撑代码具有显式签名,即它具有明确的参数,例如下面的$foo
。它总是构造一个Block
,无论大括号里面是什么:
say WHAT { key => $foo, 'a', 'b' } # (Hash)
say WHAT -> $foo { key => $foo, 'a', 'b' } # (Block)
一些支撑代码具有隐式签名:
$^foo
)会给它一个隐式签名(其中包含$foo
参数)。$_
,@_
和%_
。{ .foo }
,甚至(;; $_? is raw)
也有签名(.foo
)。与显式签名一样,如果支持的代码具有隐式签名,那么无论大括号内部是什么,它总是构造一个Block
:
say WHAT { key => $_, 'a', 'b' } # (Block)
say WHAT { key => 'value', .foo, .foo } # (Block)
Block
say WHAT { :foo; (do 'a'), (do 'b') } # (Block)
say WHAT { :foo, (do 'a'), (do 'b') } # (Hash)
第二行包含多个语句,但它们在列表中生成值,这是单个顶级语句。
Block
say WHAT { :foo, (my $bar), $baz } # (Block)
say WHAT { :foo, {my $bar}, $baz } # (Hash)
最后一行包含一个Block
作为包含声明(my $bar
)的键。但该声明属于内部Block
,而不是外部支撑代码。因此,就外部支撑代码而言,内部Block
只是一个值,因此外部支撑块仍然被解释为Hash
。
Block
smy $bar = key => 'value';
say WHAT { $bar, %baz } # (Block)
say WHAT { |%baz } # (Block)
say WHAT { %@quux } # (Block)
以上都不是以%
sigil'd变量或字面对开头的。
Hash
不属于任何前述情况的强制代码强制它成为Block
,并且它只是一个零或更多值的列表,以%
sigil'd变量或Pair
文字结构构成Hash
:
say WHAT { %foo } # (Hash)
say WHAT { %foo, ... } # (Hash)
say WHAT { foo => 42, ... } # (Hash)
say WHAT { :foo, ... } # (Hash)
say WHAT { key => $foo, 'a', 'b' } # (Hash)
say WHAT { 'a', 'b', key => $foo } # (Block)
上面的最后一个块不是以%foo
或文字对开头的。
say WHAT { %foo, 'a', 'b' } # (Hash)
say WHAT { Pair.new('key',$foo), # Pair.new is NOT a literal
'a', 'b' } # (Block)
上面的第二个块不是以%foo
或文字对开头。
Block
or Hash
interpretationBlock
,写下{;}
。要写一个空的Hash
,写下{}
。Block
而不是Hash
,请在开头写一个;
,即{; ... }
。Hash
而不是Block
,请遵循上面解释的规则或写%(...)
而不是{...}
。1请参阅以下评论关于学期位置的评论。
2大多数时候,一个有价值的DWIM必须在大多数编码人员的帮助下工作,其相关的WATs必须为社区所接受。 (当DWIM没有达到他们的意思时,WAT指的是开发者的惊喜。对于每个DWIM,都有一个或多个WAT。)
可接受的WAT有barks worse than their bites。像所有的DWIM一样,这个可以要求community vigilance and response确保它仍然是一个净赢,而不是保证弃用,社区成员的意见不同,它的咬伤程度。 cf my perspective vs Sam对这个问题的回答。