那是 Perl 6 哈希还是块? [英] Is that a Perl 6 Hash or Block?

查看:28
本文介绍了那是 Perl 6 哈希还是块?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

这是一个可能会咬到初学者的意外行为.首先,这是故意的吗?其次,Perl 6 还使用哪些其他东西来猜测要创建哪个对象?它是开始认为是 Block 还是 Hash 并稍后更改,还是最终决定?

This is a bit of unexpected behavior that's likely to bite beginners. First, is this intended? Second, what other things does Perl 6 use to guess which object to create? Does it start off thinking it's Block or Hash and change later, or does it decide on the end?

你可以用大括号和粗箭头构造一个Hash:

You can construct a Hash with braces and the fat arrow:

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

put $color-name-to-rgb.^name;  # Hash

使用其他 Pair 符号也会创建一个 Hash.

Using the other Pair notation creates a Hash too.

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

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

But, absent the fat arrow, I get a Block instead:

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

put $color-name-to-rgb.^name;  # Block

Hash 文档只提到在内部使用 $_大括号创建一个 Block.

The Hash docs only mention that using $_ inside the braces creates a Block.

还有其他定义散列的方法,但我问的是这种特殊的语法,而不是寻找我已经知道的解决方法.

There are other ways to define a hash, but I'm asking about this particular bit of syntax and not looking for the workarounds I already know about.

$ perl6 -v
This is Rakudo version 2017.04.3 built on MoarVM version 2017.04-53-g66c6dda
implementing Perl 6.c.

推荐答案

当它是一个 Hash

您的问题1和此答案仅适用于术语位置2中的支撑块.

When it's a Hash

Your question1 and this answer only apply to braced blocks in term position2.

严格遵循下面解释的规则的花括号代码构造了一个Hash:

Braced code that precisely follows the rule explained below constructs a 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)

规则

如果块是空的,或者只包含一个列表,它的第一个元素是一个 % 标记变量(例如 %foo)或一个 literal 对(例如 :bar),并且它没有签名或包含顶级语句,它是一个 Hash.否则它是一个 Block.

The rule

If the block is empty, or contains just a list whose first element is a % sigil'd variable (eg %foo) or a literal pair (eg :bar), and it does not have a signature or include top level statements, it's a Hash. Otherwise it's a Block.

  • 要强制 {...} 项构造 Block 而不是 Hash,请编写 ; 在开头即 { ;... }.

  • To force a {...} term to construct a Block instead of a Hash, write a ; at the start i.e. { ; ... }.

要写一个空的Block术语,请写{;}.

To write an empty Block term, write {;}.

要编写空的 Hash 项,请编写 {}.

To write an empty Hash term, write {}.

要强制 {...} 项构造 Hash 而不是 Block,请遵循规则(解释在本答案的其余部分详细说明),或者写 %(...) 代替.

To force a {...} term to construct a Hash instead of a Block, follow the rule (explained in detail in the rest of this answer), or write %(...) instead.

某些花括号代码具有 explicit 签名,即它具有显式参数,例如下面的 $foo.它总是构造一个 Block,不管花括号里面是什么:

Some braced code has an explicit signature, i.e. it has explicit parameters such as $foo below. It always constructs a Block no matter what's inside the braces:

say WHAT         { key => $foo, 'a', 'b' } # (Hash)
say WHAT -> $foo { key => $foo, 'a', 'b' } # (Block)

一个隐式签名也意味着它是一个Block

某些花括号代码具有隐式签名,该签名是由于块内的某些显式编码选择而生成的:

An implicit signature also means it's a Block

Some braced code has an implicit signature that is generated due to some explicit choice of coding within the block:

  • 代词"的使用{...} 内部意味着它是一个带有签名的 Block (如果它还没有显式签名,则为隐式签名).代词是 $_@_%_.

  • Use of a "pronoun" inside {...} means it's a Block with a signature (an implicit signature if it doesn't already have an explicit one). The pronouns are $_, @_, and %_.

这包括在 {...} 中隐含使用 $_ 由于没有左手的 .method 调用侧面论证.换句话说,即使 { .foo } 也有签名((;; $_? is raw)) 由于 .foo缺少左侧参数.

This includes implied use of $_ inside {...} due to a .method call with no left hand side argument. In other words, even { .foo } has a signature ((;; $_? is raw)) due to .foo's lack of a left hand side argument.

占位符"的使用变量(例如 $^foo).

Use of a "placeholder" variable (e.g. $^foo).

与显式签名一样,如果花括号代码有一个隐式签名,那么它总是构造一个Block,不管花括号里面是什么:

As with an explicit signature, if braced code has an implicit signature then it always constructs a Block no matter what's inside the braces:

say WHAT { key => $_ }                     # (Block)
say WHAT { key => 'value', .foo, .bar }    # (Block)

顶级语句意味着它是一个Block

Top level statements mean it's a Block

say WHAT { :foo; (do 'a'), (do 'b') }     # (Block)
say WHAT { :foo, (do 'a'), (do 'b') }     # (Hash)

第二行包含多个语句,但它们在作为单个顶级表达式的列表的各个元素中生成值.

The second line contains multiple statements but they're producing values within individual elements of a list that's the single top level expression.

声明就是声明,但我已经包含了这一部分,以防万一有人没有意识到这一点.

A declaration is a statement, but I've included this section just in case someone doesn't realize that.

say WHAT { :foo, $baz, {my $bar} }        # (Hash)
say WHAT { :foo, $baz, (my $bar) }        # (Block)

第一行包含一个 Block 作为包含声明(my $bar)的键.但该声明属于内部 {my $bar} Block,而不是外部 {...}.因此,就外部 {...} 而言,内部 Block 只是一个值,因此外部花括号代码仍被解释为 Hash.

The first line contains a Block as a key that contains a declaration (my $bar). But that declaration belongs to the inner {my $bar} Block, not the outer {...}. So the inner Block is just a value as far as the outer {...} is concerned, and thus that outer braced code is still interpreted as a Hash.

相反,第二行直接在外部 {...} 中声明了一个变量.所以这是一个Block.

In contrast the second line declares a variable directly within the outer {...}. So it's a Block.

回忆一下,要成为 Hash,花括号代码的内容必须是一个以 % 标记变量或 文字开头的列表 对.所以这些都产生 Blocks:

Recall that, to be a Hash, the content of braced code must be a list that begins with either a % sigil'd variable or a literal pair. So these all produce 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 这个HashBlock?"问题是 DWIM 设计的一个例子.在 Raku 文化中,好的 DWIM 设计被认为是一件好事.但是每个 DWIM 都带有相应的 WAT3.良好 DWIM 设计的关键是确保 WAT 的 bark 更糟糕比他们的叮咬4;并且树皮很有用5;并且 DWIM 的净收益被认为远远超过所有的吠叫和叮咬.6

Footnotes

1 This "Hash or Block?" question is an example of DWIM design. In Raku culture, good DWIM design is considered a good thing. But every DWIM comes with corresponding WATs3. The key to good DWIM design is ensuring that, in general, WATs' barks are worse than their bites4; and that the barks are useful5; and that the net benefits of the DWIM are considered to far outweigh all the barking and biting.6

2 术语是 Raku 对英语中名词或名词短语的模拟.这是一个价值.

2 A term is Raku's analog of a noun or noun phrase in English. It's a value.

作为术语的支撑块示例:

Examples of braced blocks that are terms:

.say given { ... }  # closure? hash?
say 42, { ... }     # closure? hash?

术语的支撑块示例:

if True { ... }     # always a closure
class foo { ... }   # always a package
put bar{ ... }      # always a hash index

这个答案只讨论作为术语的支撑块.有关术语的更多详细信息,或者更具体地说是术语位置",请参阅(语法中花括号块将被解释为术语的地方),请参阅此答案下方的注释.

This answer only discusses braced blocks that are terms. For more details about terms, or more specifically "term position" (places in the grammar where a braced block will be interpreted as a term), see the comments below this answer.

3 WAT 指的是开发人员难以置信的惊喜当他们觉得有些事情很疯狂时.众所周知,即使对于设计良好的 DWIM,对于每个对大多数人都有效的 DWIM,在大多数情况下,不可避免地会有一个或多个相关的 WAT 让一些人感到惊讶,有时,包括一些同样在其他时候受益于 DWIM.

3 WAT refers to a dev's incredulous surprise when something seems crazy to them. It's known that, even for well designed DWIMs, for each one that works for most folk, most of the time, there are inevitably one or more related WATs that surprise some folk, some of the time, including some of the same folk who at other times benefit from the DWIM.

4 与此 DWIM 相关的 WAT 的作用各不相同.它通常是一个使问题显而易见的树皮(错误消息).但它也可以更加模糊:

4 The bite of the WATs related to this DWIM varies. It's typically a bark (error message) that makes the problem obvious. But it can also be much more obscure:

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 树皮"是文档中的错误消息或警告.这些通常可以改进.cf Lock.protect({}) 失败,但出现令人惊讶的消息.

5 A "bark" is an error message or warning in documentation. These can often be improved. cf Lock.protect({}) fails, but with surprising message.

6 社区成员对于 DWIM 设计是否值得,或任何特定的 DWIM 是否值得持有不同意见.参见 我的观点 vs Sam 对这个问题的回答.

6 Community member opinions differ on whether DWIM design in general, or any given DWIM in particular, is worth it. cf my perspective vs Sam's answer to this question.

这篇关于那是 Perl 6 哈希还是块?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆