为什么作为参数传递的数组是可变的,而标量则不然?

Ste*_*ieD 7 raku

收到:

#! /usr/bin/env raku
use v6;

multi blah (@arg) { @arg = 7; }
multi blah ($arg) { $arg = '3'; }

my @array = 1, 2, 3;
blah @array;
say @array;

my $string = 'onetwothree';
blah $string;
say $string;
Run Code Online (Sandbox Code Playgroud)

得到这个:

[7]
Cannot assign to a readonly variable or a value
  in sub blah at ./chop.raku line 5
  in block <unit> at ./chop.raku line 12
Run Code Online (Sandbox Code Playgroud)

我发现这种行为令人惊讶,特别是在函数范围之外更改数组的能力。

有人可以解释一下为什么我可以更改传递给函数的数组参数而不是标量吗?有没有办法使数组在传递给函数时只读?有什么方法可以使传递给函数的标量可变吗?

cod*_*ons 9

有人可以解释一下为什么我可以更改传递给函数的数组参数而不是标量吗?

传递给函数的参数是只读的(默认情况下;更多内容见下文),因此通常无法更改。您可以修改 的原因ArrayArrays 本身是可变的(有关详细信息,请参阅文档中的列表、序列和数组页面)。这意味着,即使您无法更改Array 本身,您仍然可以更改的值Array

有没有办法使数组在传递给函数时只读?

List是 Raku 的位置数据不可变类型某种程度上;它不是深度不可变的,但这超出了这里的范围)。如果将 a 传递List给函数,该函数将无法修改该列表的内容。例如,此代码会引发错误:

my @l is List = (1, 2, 3);
sub f(@var) { @var[1] = 42 }
f @l;
Run Code Online (Sandbox Code Playgroud)

有什么方法可以使传递给函数的标量可变吗?

有两种方法,具体取决于您想要哪种类型的可变性:您可以使用is rwis copy特征。例如,您可以声明如下函数:

sub f($a is copy, $b is rw) {...}
Run Code Online (Sandbox Code Playgroud)

该声明允许&f修改$a$b。但是 for$a正在&f修改其自己的本地副本,并且不会对其调用者看到的值产生任何影响$a$b然而,With&f正在修改共享状态,并且它所做的任何更改$b即使在 的范围之外也是可见的&f

  • 您说过有两种方法可以通过将标量传递给函数来改变标量,但是“is raw”呢? (4认同)
  • 谢谢。很有帮助。今晚我一直在阅读有关这一切的内容:https://opensource.com/article/18/8/containers-perl-6 和 https://uzluisf.gitlab.io/posts/2020/04/03 /raku-containers/ 也非常有帮助。但这是您可以在文档中阅读的内容,但直到您真正开始编写代码并遇到一些令人讨厌的意外和无法解释的错误时,它才会真正起作用。 (3认同)
  • 请注意,您也可以在数组上使用“is copy”: `sub frobnicate(@a is copy) { @a.push: 42; 说@a};我的@b = 666;frobnicate@b;说@b;#[666 42][666]`。还有哈希值:-) (2认同)