运行以下简单代码,检查无符号变量的行为,产生一个奇怪的错误:
use v6.d; # Rakudo Star 2020.05.01 (Windows)
sub test ($p) {
say $p;
}
my \v1 = 1;
say v1; # v1 (ERROR)
test(v1); # v1 (ERROR)
my \v = 1;
say v; # 1 (Correct)
test(v); # 1 (Correct)
my \vv1 = 1;
say vv1; # 1 (Correct)
test(vv1); # 1 (Correct)
my \s1 = 1;
say s1; # 1 (Correct)
test(s1); # 1 (Correct)
Run Code Online (Sandbox Code Playgroud)
这是为什么?
当我们使用超出数组边界的索引对数组进行切片时,我们得到的结果是 undefined (Any)
当我们传递与惰性列表相同的切片索引时,我们将获得数组/列表的现有值(并且仅此而已):
my @a = ^5;
say @a[^10]; # (0 1 2 3 4 (Any) (Any) (Any) (Any) (Any))
say @a[lazy ^10]; # (0 1 2 3 4)
Run Code Online (Sandbox Code Playgroud)
很明显,切片索引的惰性会影响结果。
试图理解事物的方式并作为概念证明,我编写了我的切片机制的简单版本:
my @a = ^5;
my @s1 = ^10;
my @s2 = lazy ^10;
sub postcircumfix:<-[ ]-> (@container, @index) {
my $iter = @index.iterator;
gather {
loop {
my $item := $iter.pull-one;
if $item =:= IterationEnd {
last;
}
with @container[$item] {
take @container[$item]
} else {
@index.is-lazy ?? …Run Code Online (Sandbox Code Playgroud) 我们知道故障可以由 CATCH 块处理。
在下面的示例中,我们创建了一个“AdHoc”失败(在其他子中),并在一个 CATCH 块中(在我的子中)处理异常
sub my-sub {
try {
CATCH {
when X::AdHoc { say 'AdHoc Exception handled here'; .resume }
default {say 'Other Exception'; .resume}
}
my $b = other-sub();
$b.so ?? $b.say !! 'This was a Failure'.say;
}
}
sub other-sub { fail 'Failure_X' }
my-sub();
Run Code Online (Sandbox Code Playgroud)
输出如下:
AdHoc Exception handled here
This was a Failure
Run Code Online (Sandbox Code Playgroud)
我的问题是:我们如何区分 CATCH 块中的失败和“正常”异常以区分这两种情况?
我想将多维数组克隆为@a数组@b。
我以最直观的方式进行了操作,并提出了以下建议:
my @a = [0, 0, 0], [0, 0, 0], [0, 0, 0];
my @b = @a.clone;
@a[0][1] = 1;
@b[1][0] = 1;
say '@a : ' ~ @a.gist;
say '@b : ' ~ @b.gist;
Run Code Online (Sandbox Code Playgroud)
打印出来的是:
@a : [[0 1 0] [1 0 0] [0 0 0]]
@b : [[0 1 0] [1 0 0] [0 0 0]]
Run Code Online (Sandbox Code Playgroud)
那意味着两个数组@a 和@b 是绑定的?
问题:
当我们检查reduce函数时:
my $result = reduce &reduction_procedure, @array;
Run Code Online (Sandbox Code Playgroud)
我们总结了以下内部工作的简单规则:
Reduction Rules
---------------
1. For the first pair of objects from our input (@array)
we apply the reduction procedure (&reduction_procedure) and we get our first result.
2. We apply the reduction procedure (&reduction_procedure) to the result (object)
of the previous rule and the next input (object) from our input (@array),
and we get an intermediate result (object).
3. We run rule.2 for every of the remaining objects from our input (@array)
Run Code Online (Sandbox Code Playgroud)
这个简单的规则对于归约元操作符 …
在阅读和尝试签名智能匹配时,我遇到了一些奇怪的事情。
执行以下 smartmaching 签名对:
my @sigs = :($a, $b), :($a, @b), :($a, %b);
my @signatures_to_check = :($, $), :($, @), :($, %);
my $c = 0;
for @sigs -> $sig {
for @signatures_to_check -> $s {
$c++;
if $sig ~~ $s {
say " [ $c ] " ~ $sig.gist ~ ' match ' ~ $s.gist;
next;
}
say " [ $c ] " ~ $sig.gist ~ ' do NOT match ' ~ $s.gist;
}
say "\n" ~ '#' x …Run Code Online (Sandbox Code Playgroud) 在以下示例中,我尝试通过将数组 (@a)“转换”为 Capture 来动态创建 Capture。
考虑代码:
sub f (|c){
say '';
say ' List : ' ~ do {c.list.gist if c.list.elems > 0};
say ' Hash : ' ~ do {c.hash.gist if c.hash.elems > 0};
say '';
}
my $c1 = \(1,(2,3),4,5, :t1('test1'), 6,7, :t2('test2'), 8,9);
my @a = 1,(2,3),4,5, :t1('test1'), 6,7, :t2('test2'), 8,9;
my $c2 = \(|@a);
f(|$c1);
f(|@a);
f(|$c2);
Run Code Online (Sandbox Code Playgroud)
结果是:
List : (1 (2 3) 4 5 6 7 8 9)
Hash : Map.new((t1 => test1, t2 => …Run Code Online (Sandbox Code Playgroud) 在下面的简单 for 循环中,我们通过增加一个无类型变量($n)来创建一个数组(@a):
my @a = do for 1..3 {
state $n;
$n.^name, $n++;
}
say @a;
Run Code Online (Sandbox Code Playgroud)
结果是“有点”预期:
[(Any 0) (Int 1) (Int 2)]
Run Code Online (Sandbox Code Playgroud)
我说“有点”是因为我期望 $n 的第一个值是“未定义”值(Any)。
就像,在产生第一个值 (Any) 之后,随着我们增加 $n(在 $n 的第一个增量之后,我们有一个转换为 Int),赋值中还有一些时间扭曲事件,我们也得到要更改的第一个值。所以我们最终将第一个值设为 0(零)。
有人可以解释这种行为的确切机制吗?
在 Raku 文档中指出,gather-take 构造正在被惰性评估。在下面的例子中,我很难对结构的懒惰得出结论:
say 'Iterate to Infinity is : ', (1 ... Inf).WHAT;
say 'gather is : ', gather {
take 0;
my ($last, $this) = 0, 1;
loop {
take $this;
($last, $this) = $this, $last + $this;
}
}.WHAT;
say '------------------------------------';
my @f1 = lazy gather {
take 0;
my ($last, $this) = 0, 1;
loop {
take $this;
($last, $this) = $this, $last + $this;
}
}
say '@f1 : ', @f1.WHAT;
say '@f1 is lazy …Run Code Online (Sandbox Code Playgroud) 当我试图解析一个多行字符串(用制表符分隔的字符串)以查找由制表符分隔的所有值时,我偶然发现了一个“奇怪”的行为,使用连续的两个分割:
use v6.d; # 2020.01 release
my $s = "L1:C1\tL1:C2\tL1:C3\nL2:C1\tL2:C2\tL2:C3\nL3:C1\tL3:C2\tL3:C3";
say $s.split(/\n/).split(/\t/).raku;
Run Code Online (Sandbox Code Playgroud)
对应的打印输出如下:
("L1:C1", "L1:C2", "L1:C3 L2:C1", "L2:C2", "L2:C3 L3:C1", "L3:C2", "L3:C3").Seq
Run Code Online (Sandbox Code Playgroud)
“奇怪”的行为出现在结果序列的第 3 和第 5 个成员中。似乎一行的“预期”最后一个字符串和后续行的第一个字符串有重叠。
我的期望是这样的:
("L1:C1", "L1:C2", "L1:C3", "L2:C1", "L2:C2", "L2:C3", "L3:C1", "L3:C2", "L3:C3").Seq
Run Code Online (Sandbox Code Playgroud)
任何人都可以详细解释这种行为的内部运作?
为了澄清事情,我知道正确的代码是:
$s.split(/\n/)>>.split(/\t/).flat.raku
Run Code Online (Sandbox Code Playgroud)
但我的问题是关于“错误”代码的内部工作原理。Raku 是如何得出这个结果的?