这是Perl 6 Hash还是Block?

bri*_*foy 12 hash block perl6 raku

这有点意外的行为,可能会咬人初学者.首先,这是打算吗?其次,Perl 6使用什么来猜测要创建哪个对象?它是否开始认为它是Block或Hash并稍后更改,还是最终决定?

你可以用大括号和胖箭头构造一个哈希:

my $color-name-to-rgb = {
    'red' => 'FF0000',
    };

put $color-name-to-rgb.^name;  # Hash
Run Code Online (Sandbox Code Playgroud)

使用另一个Pair符号也会创建哈希.

my $color-name-to-rgb = {
    :red('FF0000'),
    };
Run Code Online (Sandbox Code Playgroud)

但是,如果没有胖箭,我会得到一个Block:

my $color-name-to-rgb = {
    'red', 'FF0000',
    };

put $color-name-to-rgb.^name;  # Block
Run Code Online (Sandbox Code Playgroud)

哈希文档仅提到使用$_大括号内创建一个.

还有其他方法来定义哈希,但我问的是这个特定的语法,而不是寻找我已经知道的解决方法.

$ perl6 -v
This is Rakudo version 2017.04.3 built on MoarVM version 2017.04-53-g66c6dda
implementing Perl 6.c.
Run Code Online (Sandbox Code Playgroud)

rai*_*iph 14

这两种方案仅适用于学期位置.(一个术语类似于英语名词.)

一个{...}足月位置是{...}除了在两种情况.

{...}如果它有任何参数,它总是一个.同样,如果它是一个或多个语句的列表.

第一种{...}情况是{...}.这是空的Block.(Block用于空{...}.)

另一种%情况是立即(忽略空白)以对文字(例如%fooPair)或:barsigil'd变量(例如Hash)开始的列表.


本答案的其余部分详细解释了上述内容.


BlockDWIM规则适用

只有位于术语位置的支撑代码才能使用此DWIM/WAT.1

一些声明示例显示:

if True { ... }   # always a block
class foo { ... } # always a package
put bar{ ... }    # always a hash index
Run Code Online (Sandbox Code Playgroud)

对于本答案的其余部分,"支撑代码"表示术语位置的支撑代码.

精确的$fooDWIM规则

  • 无参数支撑码...

  • ......只包含零个或多个值的列表......

  • ......以Blocksigil'd变量或Block 字面值开头......

...将始终构建一个Block:

say WHAT         { key => $foo, 'a', 'b' } # (Hash)
say WHAT -> $foo { key => $foo, 'a', 'b' } # (Block)
Run Code Online (Sandbox Code Playgroud)

否则,支撑代码总是构造一个$_:

say WHAT { key => $_ }                     # (Block)
say WHAT { key => 'value', .foo, .foo }    # (Block)
Run Code Online (Sandbox Code Playgroud)

始终构造一个的支撑代码@_

一些支撑代码具有显式签名,即它具有明确的参数,%_如下所示.$_无论大括号里面是什么,它总是构造一个:

say WHAT { :foo; (do 'a'), (do 'b') }     # (Block)
say WHAT { :foo, (do 'a'), (do 'b') }     # (Hash)
Run Code Online (Sandbox Code Playgroud)

一些支撑代码具有隐式签名:

  • Block在括号内使用显式占位符变量(例如)为支撑代码提供隐式签名(其中包含{ .foo }参数).

  • 在括号内使用代词((;; $_? is raw)或者.foo,它们总是显式的,或者$^foo可以是显式的或隐式的),如果它没有明确的代码,则为支撑代码提供隐式签名.

与显式签名一样,如果支撑块具有隐式签名,那么Block无论括号内部是什么,它总是构造一个.

由于它们的显式/隐式签名,以下两行都构造了一个$foo,尽管大括号内的第一个值是Block文字:

say WHAT { :foo, (my $bar), $baz }        # (Block)
say WHAT { :foo, {my $bar}, $baz }        # (Hash)
Run Code Online (Sandbox Code Playgroud)

可以构造一个的支撑代码Block

没有隐式或显式签名且只包含零个或多个逗号分隔值的列表的支撑代码可以构造一个Block取决于第一个值.

如果第一个值是Blocksigil'd变量或my $bar文字,则支撑代码构造a Block,否则为Block:

my $bar = key => 'value';
say WHAT         { $bar, %baz }            # (Block)
say WHAT         { |%baz      }            # (Block)
say WHAT         { %@quux     }            # (Block)
Run Code Online (Sandbox Code Playgroud)

如果支撑代码是Hash,那么它构造一个空Block.

强迫%Hash解释

  • 写一个空的Block,写%.写一个空的Pair,写Hash.

  • 要强制使用括号代码来构造a %foo而不是a %foo,请Block在开头写一个ie Hash.

  • 要强制使用括号代码来构造a Block而不是a {;},请遵循上面解释的规则.另请参阅Sam的回答(但从不使用Hash,即在parens之间没有任何东西,甚至没有空间,因为这是一个被删除的错误的错误{}).


1大多数时候,大多数编码人员都喜欢有价值的DWIM,其相关的WAT必须为社区所接受.(当DWIM没有达到他们的意思时,WAT指的是开发者的惊喜.对于每个DWIM,都有一个或多个WAT.)

可接受的WAT 比他们的叮咬更糟糕.像所有DWIM一样,这个可以要求社区保持警惕和响应,以确保它仍然是一个净赢,而不是保证弃用,社区成员的意见不同,它的咬伤程度.比较我的观点与Sam对这个问题的回答.

  • “在职职位”是什么意思?我们有“职位”之类的东西吗?如果是这种情况,它们应该被记录在案。 (2认同)
  • 我在设计文档中没有找到“术语位置”的匹配项。我认为这是解析(尤其是P5文化)中的一个众所周知的术语(!),因此Larry不必费心定义它。试图追捕它的尝试使我想起了我以前研究过的东西……这导致我进入[我对*“连续两个术语”错误的回答*]中的“什么是术语?”部分( /sf/ask/3554259131/#50779482)。真是la脚。我建议问拉里。 (2认同)
  • 我现在已经为此创建了一个问题 https://github.com/Raku/doc/issues/3774 应该早在那时就完成了...... (2认同)

Sam*_* M. 13

首选的Perl6方法是%( )用来创建哈希.

my $color-name-to-rgb = %(
    'red', 'FF0000',
    );
Run Code Online (Sandbox Code Playgroud)

我不建议人们使用大括号来创建哈希.如果他们想要制作哈希,那么这%( )是正确的方法.

如果你来自Perl 5世界,最好养成使用%( )而不是{ }创建哈希时的习惯.

  • 然后,文档需要一个重大更新来反映这一点.当`{}`不起作用时,提到`%()`作为替代.如果不是文档,首选的方法来源在哪里? (6认同)
  • 我似乎记得用"{}"创建哈希用于抛出错误并告诉你使用'%()'.在我看来,这种行为应该回归. (2认同)
  • 我完全同意你的评估布莱恩.我在这里打开了一个docs问题https://github.com/perl6/doc/issues/1380我们曾经在程序完成后显示弃用警告,也许这是我们在创建时可能想要为6.d添加的内容带有`{}`的哈希. (2认同)