【发布时间】:2021-11-12 19:24:48
【问题描述】:
Raku 有时会禁止重新绑定;以下两行
sub f($a) { $a := 42 }
my \var = 'foo'; var := 'not-foo';
产生编译时错误:
===SORRY!=== Error while compiling
Cannot use bind operator with this left-hand side
但是,Raku 允许在很多很多情况下重新绑定 - 包括许多让我大吃一惊的情况。以下所有成功重新绑定;每个say 输出not-foo。
my Any \a = 'foo';
say a := 'not-foo';
my Any $b := 'foo';
say $b := 'not-foo';
my @c := ('foo', 'foo');
say @c := ('not-foo', 'not-foo');
my @d is List = ('foo', 'foo');
say @d := ('not-foo', 'not-foo');
my %e := (:foo<foo>);
say %e := (:not-foo<not-foo>);
sub fn1(Any \a) { a := 'not-foo'; say a }
fn1 'foo';
sub fn2(Any $b) { $b := 'not-foo'; say $b }
fn2 'foo';
sub fn3(@c) { @c := ('not-foo', 'not-foo'); say @c }
fn3 ('foo', 'foo');
sub fn4(+@d) { @d := ('not-foo', 'not-foo'); say @d }
fn4 ('foo', 'foo');
sub fn5(@d is raw) { @d := ('not-foo', 'not-foo'); say @d }
fn5 ('foo', 'foo');
my ($one-foo, $two-foo) := ('foo', 'foo');
$one-foo := 'not-foo';
say $one-foo;
my \foo = 'foo';
say MY::<foo> := 'not-foo';
sub foo-fn { 'foo' }
MY::<&foo-fn> := { 'not-foo' }
say foo-fn;
my $absolutely-foo = 'foo';
sub fn6 { CALLER::<$absolutely-foo> := 'not-foo';}
fn6;
say $absolutely-foo;
因此,如果满足以下任一条件,目前似乎允许对任何名称重新绑定,无论是否有印记:
- 名称具有任何显式类型约束(包括
Any和@或%sigils 施加的类型约束),或者 - 重新绑定使用限定名称。
这种重新绑定当前发生在声明的变量和参数上,包括不是rw 或copy 的参数。正如最后一个示例所示,它甚至允许以(似乎?)违反词法范围的方式重新绑定。 (这个例子是基于a Roast test 注释的-- legal?,这表明我可能至少不是唯一一个发现这种行为令人惊讶的人!虽然测试重新绑定了is dynamic 变量——在某些方面,上面的行为更令人惊讶)。
据我所知,唯一不能使用其中一种方法重新绑定的名称是声明为 constant 的名称。
那么四个问题:
- 我是否正确描述了当前行为? [编辑:也就是说,我上面列出的两条规则是否正确描述了当前行为,或者正确的描述是否需要其他/附加规则?]
- 这种行为是否正确/有意/符合规范? (尽管有S03-binding 存在,但我发现关于重新绑定的内容非常少。
- 如果这种行为不是故意的,那么重新绑定的规则应该是什么?
- 有什么方法可以告诉 Raku“不要将此名称重新绑定到新值,不是真的-我是故意的”?
(这个问题取代了my earlier question,在我意识到重新绑定名称是多么容易之前我问过这个问题;我正在关闭它以支持这个问题。另一个相关问题:Is there a purpose or benefit in prohibiting sigilless variables from rebinding?,它讨论了一些与上面的几个例子相反,设计权衡是假设无符号变量不能重新绑定。)
【问题讨论】:
标签: immutability raku lexical-scope rakudo variable-binding