cod*_*ons 7 immutability rakudo lexical-scope variable-binding raku
[注意:我根据旧版本的 Rakudo 问这个问题。正如已接受的答案中所解释的,令人困惑的输出是 Rakudo bug 的结果,现已解决。我留下了下面 Q 的原始版本以供历史参考。]
\nRaku 有时会禁止重新绑定;以下两行
\nsub f($a) { $a := 42 }\nmy \\var = \'foo\'; var := \'not-foo\';\nRun Code Online (Sandbox Code Playgroud)\n产生编译时错误:
\n===SORRY!=== Error while compiling \nCannot use bind operator with this left-hand side\nRun Code Online (Sandbox Code Playgroud)\n然而,Raku 允许在很多很多情况下重新绑定 \xe2\x80\x93 ,包括许多让我大吃一惊的情况。以下所有内容都成功重新绑定;每个say输出not-foo。
sub f($a) { $a := 42 }\nmy \\var = \'foo\'; var := \'not-foo\';\nRun Code Online (Sandbox Code Playgroud)\n因此,目前看来,只要满足以下任一条件,任何名称都可以重新绑定,无论是否有印记:
\nAny施加的类型约束),或者@%目前,声明的变量和参数都会发生这种重新绑定,并且包括不是rw或 的参数copy。正如最后一个示例所示,它甚至允许以(似乎?)违反词法范围的方式重新绑定。(该示例基于带有注释的Roast 测试-- legal?,这表明我可能至少不是唯一一个发现这种行为令人惊讶的人!尽管该测试is dynamic在某些情况下重新绑定了变量 \xe2\x80\x93方式,上面的行为更令人惊讶)。
据我所知,唯一不能使用这些方法之一重新绑定的名称是那些声明为constant.
那么四个问题:
\n(这个问题取代了我之前的问题,在我意识到重新绑定名称是多么容易之前我就问过这个问题;我将关闭它以支持这个问题。另一个相关问题:禁止无符号变量是否有目的或好处来自重新绑定? ,其中讨论了基于无符号变量不能的假设的一些设计权衡重新绑定的
\n我在问题中询问的不一致行为是 Rakudo bug \xe2\x80\x93 Rakudo 的结果,Rakudo 允许在某些不应该的情况下重新绑定。此错误已在Rakudo/Rakudo#4536中解决。
\n经过此决议后,重新绑定的规则为:
\nis copy或is rwTraits重新绑定。\nsub f($a) { $a := 42 }是非法的):=。例如,在 中my ($var1, $var2) := (\'foo\', \'bar\'),右侧是签名,因此$var1和$var2不能反弹。应用这些规则意味着现在禁止以下所有重新绑定(在提出问题时允许):
\nmy Any \\a = \'foo\';\nsay a := \'not-foo\';\n\nsub fn1(Any \\a) { a := \'not-foo\'; say a }\nfn1 \'foo\';\nsub fn2(Any $b) { $b := \'not-foo\'; say $b }\nfn2 \'foo\';\nsub fn3(@c) { @c := (\'not-foo\', \'not-foo\'); say @c }\nfn3 (\'foo\', \'foo\');\nsub fn4(+@d) { @d := (\'not-foo\', \'not-foo\'); say @d }\nfn4 (\'foo\', \'foo\');\nsub fn5(@d is raw) { @d := (\'not-foo\', \'not-foo\'); say @d }\nfn5 (\'foo\', \'foo\');\n\nmy ($one-foo, $two-foo) := (\'foo\', \'foo\');\n$one-foo := \'not-foo\';\nsay $one-foo;\nRun Code Online (Sandbox Code Playgroud)\n相反,应用这些规则意味着问题中显示的一些其他重新绑定是(正确)允许的:
\nmy Any $b := \'foo\';\nsay $b := \'not-foo\';\nmy @c := (\'foo\', \'foo\');\nsay @c := (\'not-foo\', \'not-foo\');\nmy @d is List = (\'foo\', \'foo\');\nsay @d := (\'not-foo\', \'not-foo\');\nmy %e := (:foo<foo>);\nsay %e := (:not-foo<not-foo>);\nRun Code Online (Sandbox Code Playgroud)\n最后,问题中显示的一些示例涉及修改(伪)包的内容。这允许重新绑定,否则上述规则将禁止重新绑定:
\nmy \\foo = \'foo\';\nsay MY::<foo> := \'not-foo\';\nsub foo-fn { \'foo\' }\nMY::<&foo-fn> := { \'not-foo\' }\nsay foo-fn;\n\nmy $absolutely-foo = \'foo\';\nsub fn6 { CALLER::<$absolutely-foo> := \'not-foo\';}\nfn6;\nsay $absolutely-foo;\nRun Code Online (Sandbox Code Playgroud)\n然而,就像使用元对象协议访问私有方法/属性一样,使用伪包来破坏 Raku 的正常规则应该是极端的最后手段,并且不享有与 Raku 其他方面相同的稳定性保证。
\n