定义与使用Perl6哈希键存在

问题描述 投票:4回答:3

我从Perl5的学习Perl6。

我在看副词:exists https://docs.perl6.org/type/Hash#:exists但没有一个:defined副词

但我担心,因为有perl5的的existsdefined之间的区别:What's the difference between exists and defined?

我怎样才能做这样的事情在Perl6?

if (defined $hash{key}) {
   $hash{key}++;
} else {
   $hash{key} = 1;
}
perl6
3个回答
6
投票
if defined %hash{'key'} {
   %hash{'key'}++;
} else {
   %hash{'key'} = 1;
}

使用defined程序或方法。见5to6-perlfunc -- defined


3
投票

你已经得到了确切的代码可以在Perl 6进行简单得多,因为的自动激活:

my %foo;
%foo<thekey>++;
say %foo.perl; # => {:thekey(1)}

除此之外,defined %foo<thekey>%foo<thekey>:exists之间的区别是,你可以在给定的密钥放在一个未定义的值到哈希,它会回答True:existsFalsedefined


3
投票

defined是一个值的一个属性。

exists是散列索引操作的变型选择器。

这是既Perl5的和Perl6如此。 这只是他们的方式他们处理是不同的。


假设你有一个像这样的哈希:

my %h = ( a => 1, b => 2, c => Int );

它有三个键:

say %h.keys; # (a b c)

你可以得到一个键关联的值:

my $value = %h{'a'};

你可以问价值,如果它是defined

say defined $value; # True

现在让我们尝试将其与c

my $value = %h{'c'};
say defined $value; # False

并与D

my $value = %h{'D'};
say defined $value; # False

请注意,即使D是不是在哈希键,你回来的价值看起来与作为仰视c

该值不知道你是如何得到阿霍德它。它没有对散列索引操作的线索。 这是相同的,即使你不把它存储在一个变量。

say defined %h{'c'}; # False
say defined %h{'D'}; # False

所以我们要告诉索引操作,而不是给我们的信息。

my $exists = %h{'D'}:exists;
say $exists; # False

此外,如果你使用%h{'D'}的结果作为一个容器,它[神奇]开始存在。

say %h{'D'}:exists; # False

say %h{'D'}.perl;   # Any
say %h{'D'}:exists; # False

%h{'D'}++;
say %h{'D'}:exists; # True

say %h{'D'}; # 1

那么,为什么它比Perl5的不同?

在Perl5中existsdefined是关键字。在Perl6他们不是。 他们不是特别以任何方式,形状或形式Perl6。

这里是Perl5的版本检查exists

use v5.12.0;
use warnings;

my %h = ( a => 1, b => 2, c => undef );

my $exists = exists $h{D};
say $exists ? 'True' : 'False'; # False

如果调用-MO=Concise编译器,你会得到它会执行该操作码的列表。

这里就是这样显示exists是操作码的一部分:

…
d     <;> nextstate(main 5 -e:1) v:%,us,*,&,{,$,fea=2 ->e

g     <2> sassign vKS/2 ->h                          # <----- =

-        <1> ex-exists sK/1 ->f                      # <-\
e           <+> multideref($h{"D"}) sK/EXISTS ->f    # <--+-- exists $h{D}
-              <0> ex-padhv sR ->e                   # <-/

f        <0> padsv[$exists:5,6] sRM*/LVINTRO ->g     # <----- $exists

h     <;> nextstate(main 6 -e:1) v:%,us,*,&,{,$,fea=2 ->i
…

multideref($h{"D"})标有EXISTS,并有ex-exists操作码。

对于defined上市是非常相似的。


一个Perl6的设计目标是让尽可能少的特殊情况成为可能。这就是为什么既不existsdefined是关键字。

如果你找哪里defined在Rakudo代码库,你发现这一点:

proto sub defined(Mu, *%) is pure {*}
multi sub defined(Mu \x) { x.defined }

defined仅仅是一个子程序,它有一个价值,并呼吁该值.defined方法。

由于它的方法调用,价值得到它是否被认为是定义或没有发言权。

所有的值继承默认是Mu.defined source

proto method defined(|) {*}
multi method defined(Mu:U: --> False) { }
multi method defined(Mu:D: --> True)  { }

所以默认为是未定义的类型的对象,并且被定义的实例。

一个值得注意的例外是Failure对象:

multi method defined(Failure:D: --> False) { $!handled = 1 }

这样就使得不定义为看到失败对象的实例。这也将导致若不考虑自己处理。 (它被垃圾回收时如果故障不处理它会抛出一个警告。)


那么,关于qazxsw上qazxsw POI兴趣点? 在Perl 6中的“正常”操作符被定义为与一个特殊的名字子程序。

:exists

需要注意的是postcircumfix操作%h{'D'}由几个多潜艇的支持,但我们真的只需要看看sub foo (%hash, $key){} say &foo.signature.perl; # :(%hash, $key) say &postcircumfix:<{ }>.signature.perl; # :($, $?, Mu $?, *%)

{ }

您可以忽略大多认为。要注意的关键是one of them。 默认情况下,命名参数是可选的,没有得到其多被选中的发言权。为了multi sub postcircumfix:<{ }>( \SELF, \key, Bool() :$exists!, *%other ) is raw { SLICE_ONE_HASH( SELF, key, 'exists', $exists, %other ) } 迫使这一个将被选择它必须被标记为需要:$exists!

每当你看到:exists你可以短想到它!:exists。 (另外:exists(True)是短期的和exists => True :$exists。)

所以,这两个线路的功能相同:

:exists($exists)

它告诉操作员(子程序)使用exists => $exists变化。

请注意,它也沿着my $exists = %h{'D'}:exists; my $exists = postcircumfix:<{ }> %h, 'D', exists => True; 的值,这意味着它可以做倒立存在检查通过。

exists

$exists是短期的say %h{'c'}:exists; # True say %h{'c'}:!exists; # False say %h{'D'}:exists; # False say %h{'D'}:!exists; # True :!exists


所以没有postcircumfix :exists(False)exists => False变化的原因是,并不需要是一个。只是问,如果它被定义所得到的值。

最新问题
© www.soinside.com 2019 - 2024. All rights reserved.