当前位置: 首页 > 知识库问答 >
问题:

那是Perl 6哈希还是块?

叶茂
2023-03-14

这是一种可能会咬伤初学者的意外行为。首先,这是有意的吗?其次,Perl 6还使用哪些其他东西来猜测要创建哪个对象?它一开始是认为它是块还是散列,然后再更改,还是最终决定?

可以使用大括号和fat箭头构造哈希:

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

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

使用另一对表示法也会创建一个哈希。

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

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

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

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

哈希文档只提到在大括号内使用$\uCode创建块。

还有其他方法可以定义哈希,但我询问的是这种特定的语法,而不是寻找我已经知道的解决方法。

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

共有2个答案

微生恩
2023-03-14

首选的Perl6方法是使用%()创建哈希。

my $color-name-to-rgb = %(
    'red', 'FF0000',
    );

我不建议人们使用大括号来创建散列,如果他们想创建散列,那么%( )是正确的方法。

如果您来自Perl 5世界,最好养成在创建哈希时使用<代码>%()<代码>而不是<代码>{}<代码>的习惯。

景俊拔
2023-03-14

您的问题1和此答案仅适用于术语位置2中的括号块。

完全遵循下面解释的规则的大括号代码构造哈希:

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术语,请编写{;}

    要编写空Hash术语,请编写{}

    要强制{...}术语构造Hash而不是Block,请遵循规则(在本答案的其余部分中详细解释),或改为编写%(...)

    一些带大括号的代码具有显式签名,即它具有显式参数,如下面的$foo。无论大括号内有什么,它总是构造一个块:

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

    一些带大括号的代码有一个隐式签名,该签名是由于在块内显式选择编码而生成的:

    >

  • {...}中使用“代词”意味着它是具有签名的Block(如果它还没有显式签名,则是隐式签名)。代词是$_@_%_

    这包括由于没有左侧参数的. method调用而在{...}中隐含使用$_。换句话说,由于. foo缺乏左侧参数,即使{. foo}也有签名((;; $ _?是原始的))。

    使用“占位符”变量(例如,$^foo)。

    与显式签名一样,如果大括号中的代码具有隐式签名,则无论大括号中有什么内容,它都会构造一个块:

    say WHAT { key => $_ }                     # (Block)
    say WHAT { key => 'value', .foo, .bar }    # (Block)
    
    say WHAT { :foo; (do 'a'), (do 'b') }     # (Block)
    say WHAT { :foo, (do 'a'), (do 'b') }     # (Hash)
    

    第二行包含多个语句,但它们在一个列表的单个元素中生成值,该列表是一个顶级表达式。

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

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

    第一行包含一个块,作为包含声明的键(my$bar)。但该声明属于内部的{my$bar}块,而不是外部的{…} 。因此,内部块与外部块一样,只是一个值 ,因此外括号代码仍被解释为哈希。

    相反,第二行直接在外部{代码>{…}中声明一个变量 。所以这是一个块。

    回想一下,要成为散列,大括号代码的内容必须是以sigil'd变量或文本对开头的列表。所以这些都会产生块:

    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这个“HashorBlock?”问题是DWIM设计的一个例子。在Raku文化中,良好的DWIM设计被认为是一件好事。但是每个DWIM都带有相应的WAT3。良好的DWIM设计的关键是确保,总的来说,WAT的吠叫比它们的叮咬更糟糕4;并且吠叫是有用的5;并且DWIM的净收益被认为远远超过所有吠叫和叮咬。6

    术语是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
    

    此答案仅讨论作为术语的括号块。有关术语的更多详细信息,或更具体地“术语位置”(语法中括号块将被解释为术语的位置),请参阅此答案下方的注释。

    WAT指的是开发人员在某些事情看起来很疯狂时的难以置信的惊讶。众所周知,即使对于设计精良的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?????
    

    “吠叫”是文档中的错误消息或警告。这些通常可以改进。cf锁。protect({})失败,但出现了令人惊讶的消息。

    社区成员对DWIM总体设计或任何特定DWIM设计是否值得持有不同意见。cf我的观点与Sam对这个问题的回答。

  •  类似资料:
    • 从原理到应用分析什么是哈希? 一、什么是哈希? 哈希(hash):将任意长度的输入(关键字),通过Hash算法变成固定长度的输出。这个映射的规则就是对应的Hash算法,而原始数据映射后的二进制串就是哈希值,通常哈希值代表了关键字的存储位置。 但是为什么要这样做呢?或者说,哈希是怎样来的呢? 哈希的出现解决了两个问题:存储和搜索。 1. 存储(数据结构):如果在容器中保存对象及其关联的键,并且不用键

    • 问题内容: HashMap中的Hash Collision或Hashing Collision并不是一个新话题,我遇到了多个博客和讨论区,解释了如何产生Hash Collision或如何以模棱两可和详细的方式避免它。我最近在一次采访中遇到了这个问题。我有很多事情要解释,但我认为准确地给出正确的解释真的很困难。抱歉,如果我在这里重复我的问题,请给我准确的答案: 哈希冲突到底是什么?它是一项功能或常见

    • 问题内容: 我上AngularJS网址项目已经从改变到自上次我在我的项目工作… 在网络上找不到任何东西,有人知道这是什么吗? 问题答案: 它是AngularJS 1.6的新增功能,它添加了新的哈希前缀。 由于aa077e8,用于哈希爆炸URL 的默认哈希前缀已从空字符串()更改为爆炸()。如果您的应用程序不使用HTML5模式或正在不支持HTML5模式的浏览器上运行,并且您尚未指定自己的哈希前缀,则

    • 主要内容:哈希表的构建,哈希函数的构造,处理冲突的方法,总结前面介绍了静态 查找表以及动态查找表中的一些查找方法,其查找的过程都无法避免同查找表中的数据进行比较,查找算法的效率很大程度取决于同表中数据的查找次数。 而本节所介绍的 哈希表可以通过关键字直接找到数据的存储位置,不需要进行任何的比较,其查找的效率相较于前面所介绍的查找算法是更高的。 哈希表的构建 在初中的数学课本中学习过函数的相关知识,给定一个 x,通过一个数学公式,只需要将 x 的值带入公式就

    • 问题内容: 我上AngularJS网址项目已经从改变到自上次我在我的项目工作… 在网络上找不到任何东西,有人知道这是什么吗? 问题答案: 它是AngularJS 1.6的新增功能,它添加了新的哈希前缀。 由于aa077e8,用于哈希爆炸URL的默认哈希前缀已从空字符串()更改为爆炸()。如果您的应用程序不使用HTML5模式或正在不支持HTML5模式的浏览器上运行,并且您尚未指定自己的哈希前缀,则客

    • 哈希是键/值对 如果你想按名字查询,那么需要哈希。哈希的键必须唯一,但值可以是任意标量。 有时候你仍然会看到人们称它为“关联数组”,但不要想当然的把它作为数组。 通过键/值对列表来创建哈希 使用键/值对列表创建哈希: my %stooges = ( 'Moe', 'Howard', 'Larry', 'Fine', 'Curly', 'Howard', 'Iggy'