my %hash =
two => 2,
three => 3,
one => 1,
;
for %hash.sort(*.key)>>.kv -> ($key, $value) {
say "'$key' => '$value'";
}
%hash.sort({.key})>>.kv
是否等同于以上排序?
为什么没有超级>>
提示这种情况不起作用?
答案 0 :(得分:9)
由于在列表中调用.kv
会返回您不想要的index, Pair
列表列表;你不能只是致电.kv
。因此,您必须通过调用每个.kv
上的>>.kv
方法单独从列表中的Pair对象中提取密钥和值。{/ 1}}。
您也可以使用.map(*.kv)
代替。
如果有意义的话,>>.kv
语法允许实现将工作分散到多个线程上
(目前Rakudo只是以半随机顺序完成工作,以防止人们使用该功能错误)
通过使用子签名中的副词提取属性,有另一种编写循环的方法:
for %hash.sort -> (:$key, :$value) {
say "'$key' => '$value'";
}
for %hash.sort -> $pair (:$key, :$value) {
say $pair;
say $key === $pair.key and $value === $pair.value; # True
}
# :$key is short for :key($key)
for %hash.sort -> (:key($k), :value($v)) {
say "'$k' => '$v'";
}
这对于没有创建公共属性列表的方法的其他对象非常有用
class C { has $.a; has $.b; has $.c; has $!private-value }
my $c = 5;
my $obj = C.new(:a<A>,:b(1),:$c);
given $obj -> ( :$a, :b($b), :$c) ) {
say "$a $b $c";
}
# ignore $.a by using an unnamed scalar
given $obj -> ( :a($), :$b, :$c ) { ... }
# places any unspecified public attributes in %others
given $obj -> ( :$a, :$b, *%others ) {
.say for keys %others; # c
}
# ignores any unspecified attributes
# useful to allow subclasses to add more attributes
# or to just drop any values you don't care about
given $obj -> ( :$a, :$b, *% ) { ... }
# fails because it doesn't handle the public c attribute
# in the sub-signature
given $obj -> ( :$a, :$b ) { ... }
这只是签名可能的开始。
在本例中,子例程和方法签名中也允许使用以下所有内容,可选,并且完全过度杀戮。 在限制可能的候选人的多子方法和多方法中它非常有用。
for 'one' => 1, 1/3
->
# Type is an alias to the object type
::Type Any $_ # Any is the default type requirement
# the public attributes of the object
(
::A-Type Any :key( :numerator( $a ) ),
::B-Type Any :value( :denominator( $b ) ) where $b >= 1,
)
{
my Type $obj = $_; # new variable declared as having the same type
my A-Type $new-a = $a;
my B-Type $new-b = $b;
# could have used $_.^name or .^name instead of Type.^name
# so you don't actually have to add the alias to the signature
# to get the name of the arguments type
say Type.^name, ' ', $_;
say ' ', A-Type.^name, ' ', $a;
say ' ', B-Type.^name, ' ', $b;
}
Pair one => 1
Str one
Int 1
Rat 0.333333
Int 1
Int 3
至于使用.sort({.key})
,是基本相同的事情,因为sort
接受Callable那里的任何内容。
我想指出,你甚至不需要为sort
提供论据,因为它的默认设置甚至比你提供的更聪明。
Perl 6有许多创建和访问Callable内容的方法。所以以下任何一项都有效:
*.key
{ .key } # { $_.key }
-> $_ { .key } # basically what the previous line turns into
{ $^placeholder-var.key }
sub ($_) { .key }
&a-subroutine-reference # you would have to create the subroutine though
此外,由于所有普通运算符实际上都是子例程,因此您可以在需要Callable的其他位置使用它们。 (我无法想到那个在那个地方有效的人)
&infix:<+> # the subroutines responsible for the numeric addition operator
&[+] # ditto
&prefix:<++>
&postfix:<++>
# etc
答案 1 :(得分:6)
据我所知,两个版本之间的差异是使用带有隐式$_
参数的块而不是使用Whatever-Star,因此它们确实是等效的。
这是Perl,因此有多种方法可以做到:
*.key
{ .key }
{ $^arg.key }
-> $arg { $arg.key }
为什么没有超级
>>
提示,这种方法不起作用?
sort
强制哈希到一对对象列表,这就是你得到的:
say %hash.sort(*.key).perl;
# ("one" => "1", "three" => "3", "two" => "2")
要摆脱这些对,你需要遍历列表并在每个列表上调用.kv
:
say %hash.sort(*.key)>>.kv.perl;
# (("one", "1"), ("three", "3"), ("two", "2"))
say %hash.sort(*.key).map(*.kv).perl;
# (("one", "1"), ("three", "3"), ("two", "2"))
您可以在致电Hash
之前强制.kv
:
say %hash.sort(*.key).hash.kv.perl;
# ("one", "1", "three", "3", "two", "2")
但这当然会破坏练习的目的,因为哈希排序不能依赖。
您可能已经注意到,根据您编写代码的准确程度,您将获得不同的结果。如果没有尾随 .list
,你得到的实际上是Parcel
而不是List
,但语义尚未最终确定。
请注意,即使返回的对象都使用简单的括号进行perlify,但有些是parcel,有些是列表,您可以通过调用.WHAT
来检查。这仍在进行中。
另请注意其中一些变体的内括号,您可以通过调用.flat
来消除这些变体。如果您这样做,则可以使用-> $key, $value
作为for循环的签名,而不是-> ($key, $value)
(或更明确地,-> $anon ($key, $value)
),它使用签名绑定来解包包裹。
而不是使用.kv
,您可以使用相同的方法来解压缩对象对象:
for %hash.sort(*.key) -> (:$key, :$value) {
say "'$key' => '$value'";
}