我从Perl5的学习Perl6。
我在看副词:exists
https://docs.perl6.org/type/Hash#:exists但没有一个:defined
副词
但我担心,因为有perl5的的exists
&defined
之间的区别:What's the difference between exists and defined?
我怎样才能做这样的事情在Perl6?
if (defined $hash{key}) {
$hash{key}++;
} else {
$hash{key} = 1;
}
if defined %hash{'key'} {
%hash{'key'}++;
} else {
%hash{'key'} = 1;
}
使用defined
程序或方法。见5to6-perlfunc -- defined
你已经得到了确切的代码可以在Perl 6进行简单得多,因为的自动激活:
my %foo;
%foo<thekey>++;
say %foo.perl; # => {:thekey(1)}
除此之外,defined %foo<thekey>
和%foo<thekey>:exists
之间的区别是,你可以在给定的密钥放在一个未定义的值到哈希,它会回答True
到:exists
但False
到defined
。
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中exists
和defined
是关键字。在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的设计目标是让尽可能少的特殊情况成为可能。这就是为什么既不exists
或defined
是关键字。
如果你找哪里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
变化的原因是,并不需要是一个。只是问,如果它被定义所得到的值。