当它是Hash
您的问题1和这个答案仅适用于术语位置2的支撑块。
完全遵循下面解释的规则的大括号代码构造了一个Hash:
say WHAT { } # (Hash)
say WHAT { %foo } # (Hash)
say WHAT { %foo, ... } # (Hash)
say WHAT { foo => 42, ... } # (Hash)
say WHAT { :foo, ... } # (Hash)
say WHAT { key => $foo, ... } # (Hash)
规则
如果块是空的,或者只包含一个列表,其第一个元素是% sigil'd 变量(例如%foo)或文字对(例如:bar),它确实没有有签名或包含顶级语句,它是Hash。否则为Block。
强制Block或Hash解释
显式签名意味着它是Block
一些大括号代码具有 显式 签名,即它具有显式参数,例如下面的 $foo。不管大括号里面是什么,它总是构造一个Block:
say WHAT { key => $foo, 'a', 'b' } # (Hash)
say WHAT -> $foo { key => $foo, 'a', 'b' } # (Block)
隐式签名也意味着它是Block
某些大括号代码具有 隐式 签名,该签名是由于块内的某些 显式 编码选择而生成的:
与显式签名一样,如果大括号代码具有隐式签名,则无论大括号内是什么,它总是构造一个 Block:
say WHAT { key => $_ } # (Block)
say WHAT { key => 'value', .foo, .bar } # (Block)
顶级语句意味着它是Block
say WHAT { :foo; (do 'a'), (do 'b') } # (Block)
say WHAT { :foo, (do 'a'), (do 'b') } # (Hash)
第二行包含多个语句,但它们在作为单个顶级表达式的列表的各个元素中生成值。
标识符的顶级声明意味着它是Block
声明是一种声明,但我将这一部分包括在内,以防有人没有意识到这一点。
say WHAT { :foo, $baz, {my $bar} } # (Hash)
say WHAT { :foo, $baz, (my $bar) } # (Block)
第一行包含一个 Block 作为包含声明 (my $bar) 的键。但是该声明属于内部{my $bar}Block,而不是外部{...}。因此,就外部{...} 而言,内部Block 只是一个值,因此外部大括号代码仍被解释为Hash。
相比之下,第二行直接在外部{...} 中声明了一个变量。所以它是Block。
还是Blocks,而不是Hashs
回想一下,要成为Hash,花括号代码的内容必须是一个以% sigil 变量或literal 对开头的列表。所以这些都产生Blocks:
my $bar = key => 'value';
say WHAT { $bar, %baz } # (Block)
say WHAT { |%baz } # (Block)
say WHAT { %@quux } # (Block)
say WHAT { 'a', 'b', key => $foo } # (Block)
say WHAT { Pair.new: 'key', $foo } # (Block)
脚注
1 这个“Hash 或 Block?” question是DWIM设计的一个例子。在 Raku 文化中,好的 DWIM 设计被认为是一件好事。但是每个 DWIM 都带有相应的 WAT3。良好的 DWIM 设计的关键是确保 WAT 的 barks are worse than their bites4;并且树皮很有用5;并且 DWIM 的净收益被认为远远超过了所有的吠叫和叮咬。6
2 术语是 Raku 对英语中名词或名词短语的类比。这是一个值。
作为术语的大括号块示例:
.say given { ... } # closure? hash?
say 42, { ... } # closure? hash?
非术语的大括号块示例:
if True { ... } # always a closure
class foo { ... } # always a package
put bar{ ... } # always a hash index
此答案仅讨论作为术语的大括号块。有关术语的更多详细信息,或者更具体地说是“术语位置”(语法中括号块将被解释为术语的位置),请参阅此答案下方的 cmets。
3WAT 指的是开发人员在某些事情看起来很疯狂时的难以置信的惊喜。众所周知,即使对于设计良好的 DWIM,对于每个适用于大多数人的 DWIM,在大多数情况下,不可避免地会有一个或多个相关的 WAT 让一些人感到惊讶,有时,包括一些相同的人,他们在其他时间受益于 DWIM。
4 与此 DWIM 相关的 WAT 的作用各不相同。它通常是使问题显而易见的吠声(错误消息)。但它也可能更加晦涩:
say { a => 42 }() ; # No such method 'CALL-ME' for invocant of type 'Hash' WAT? Oh.
say { a => $_ }<a> ; # Type Block does not support associative indexing. WAT? Oh.
say { a => $_, b => 42, c => 99 } .elems # 1 WAT?????
5 “吠叫”是文档中的错误消息或警告。这些通常可以改进。参考Lock.protect({}) fails, but with surprising message。
6 社区成员对于一般的 DWIM 设计或任何特定的 DWIM 是否值得持有不同意见。 cf my perspective vs Sam 对这个问题的回答。