为什么Perl 6 Str做位置角色,我如何更改[]?
我玩弄了一个字符串的位置界面。我知道How can I slice a string like Python does in Perl 6?,但我很好奇,如果我可以让这件事情只为咯咯笑。为什么Perl 6 Str做位置角色,我如何更改[]?
我想出了这个例子。阅读立场是好的,但我不知道如何设置了multi
处理一个任务:
multi postcircumfix:<[ ]> (Str:D $s, Int:D $n --> Str) {
$s.substr: $n, 1
}
multi postcircumfix:<[ ]> (Str:D $s, Range:D $r --> Str) {
$s.substr: $r.min, $r.max - $r.min + 1
}
multi postcircumfix:<[ ]> (Str:D $s, List:D $i --> List) {
map({ $s.substr: $_, 1 }, @$i).list
}
multi postcircumfix:<[ ]> (Str:D $s, Int:D $n, *@a --> Str) is rw {
put "Calling rw version";
}
my $string = 'The quick, purple butterfly';
{ # Works
my $single = $string[0];
say $single;
}
{ # Works
my $substring = $string[5..9];
say $substring;
}
{ # Works
my $substring = $string[1,3,5,7];
say $substring;
}
{ # NOPE!
$string[2] = 'Perl';
say $string;
}
最后一个不工作:
T
uick,
(h u c)
Index out of range. Is: 2, should be in 0..0
in block <unit> at substring.p6 line 36
Actually thrown at:
in block <unit> at substring.p6 line 36
我不认为这虽然会起作用。我不知道我应该做什么样的签名或特征。
$ perl6
> "some string"[0]
some string
的文档大多意味着[]
工作的事情上做Positional角色,而这些东西都是一样的东西名单。从[]
docs in operators:
用于位置访问@container,a.k.a.“数组索引操作符”的零个或多个元素的通用接口。
但令人惊讶的Str
做必要的角色,即使它不是一个@container
(据我所知):
> "some string".does('Positional')
True
有没有一种方法来测试的东西是@container
?
有没有办法让事情列出它的所有角色?
现在,知道一个字符串可以响应[]
,我怎样才能找出什么签名将匹配?我想知道正确的签名用于定义我自己的版本,通过[]
写入此字符串。实现这一
的方法之一,是通过扩大Str
类,因为你真的只需要重写AT-POS
方法(Str
通常从Any
继承):
use MONKEY;
augment class Str {
method AT-POS($a) {
self.substr($a,1)
}
}
say "abcde"[3] # d
say "abcde"[^3] # (a b c)
更多信息可以在这里找到: https://docs.perl6.org/language/subscripts#Methods_to_implement_for_positional_subscripting
有一个模块,目的是让你这样做:
https://github.com/zoffixznet/perl6-Pythonic-Str
但是:
此模块不提供Str.AT-POS或使海峡型做阵地或可迭代的角色。后者由于内在假设Str类型不起这些作用而导致核心和非核心代码的各种后果。这意味着简单的英语是你只能使用postcircumfix操作符为你的字符串编制索引,并且不能将它们当作字符列表来处理 - 如果你需要的话只需调用.comb。`
要正确地使您rw
版本的工作,你首先需要做哪些可能会也发生突变rw
的海峡,它需要返回的东西这反过来也rw
。对于字符串的具体情况,你可以简单地做:
multi postcircumfix:<[ ]> (Str:D $s is rw, Int:D $i --> Str) is rw {
return $s.substr-rw: $i, 1;
}
很多时候,你会希望有一个rw
子程序返回的Proxy
一个实例:
multi postcircumfix:<[ ]> (Str:D $s is rw, Int:D $i --> Str) is rw {
Proxy.new: FETCH => sub { $s.substr: $i },
STORE => sub -> $newval { $s.substr-rw($i, 1) = $newval }
}
虽然我还没有看到使用它的生产代码,还有一个return-rw
运营商,您偶尔需要它,而不是return
。
sub identity($x is rw) is rw { return-rw $x }
identity(my $y) = 42; # Works, $y is 42.
sub identity-fail($x is rw) is rw { return $x }
identity-fail(my $z) = 42; # Fails: "Cannot assign to a readonly variable or a value"
如果函数到达而不执行return
,return-rw
或抛出异常结束,则返回最后语句的值,和(目前),这表现为好像它是前面return-rw
。
sub identity2($x is rw) is rw { $x }
identity2(my $w) = 42; # Works, $w is 42.
但是,同样的事情也不会发生在例如'Int'中。它不会做位置。 –
你滥用'.does' - 它期望一个类型对象(或者看[实现])(https://github.com/rakudo/rakudo/blob/43c1767/src/core/Mu.pm#L703 ('Positional')'等价于'“一些字符串”.does(Str)',而不是' “一些字符串”.does(Positional)' – Christoph
然后'.does'应该抱怨那个。 –