有没有办法检测某些东西是否不可变?
在 Raku 中,标量可能是不可变的,也可能是实际变量:
my $a := 6; # constant
my $b = 6; # variable
是否有一种编程方法来检查标量是否不可变,而无需尝试更改它并查看它是否有效?
回答
首先,稍微修正一下术语(不要吹毛求疵,只是因为这个领域有点棘手,准确使用我们的术语会有所帮助)。
说这my $a := 6是一个常数是不对的;该表达式绑定 $a到 value 6,这会阻止您将不同的值分配给 $a (使用=运算符)。但是,您仍然可以将新值重新绑定到$a(使用:=运算符)。这意味着$a从某种意义上说,它仍然可以变异——或者,至少,可以指向新的东西。对于真正的常量$a,您应该使用constant $a或更改$a为无符号变量 ( my a = 6)。
现在来回答您的问题:要确定$a是绑定还是分配给某个值,您可以使用$a.VAR.WHAT. 如果$a被赋值,这将返回容器的类型,(Scalar);如果它是绑定的,那么它将返回绑定值的类型。
据我所知,没有办法区$a分值的绑定和常量的绑定之间的区别,尽管我很乐意在这方面出错。
下面的代码说明了我刚才所说的:
my $a = 1;
say $a.VAR.WHAT; # OUTPUT: «(Scalar)»
$a = 2;
say $a; # OUTPUT: «2»
my $b := 1;
say $b.VAR.WHAT;# OUTPUT: «(Int)»
$b := 2;
say $b; # OUTPUT: «2»
constant $c = 1;
say $c.VAR.WHAT; # OUTPUT: «(Int)»
# $c := 2; ILLEGAL
say $c; # OUTPUT: «1»
- 事实上,`constant $a = 42` 和 `my $a := 42` 之间没有运行时差异。重新绑定到它的可能性是在编译时确定的,当编译器“看到”左侧被定义为“常量”并决定抛出“无法在左侧使用绑定运算符”错误时。
- “对于真正的常量 `$a`,您应该使用 `constant $a` 或将 `$a` 更改为无符号变量(`my a = 6`)。” 我认为脚注是有序的。(或者可能是一个略带术语技巧的网站。)您所说的恒定性仅与绑定到变量的值的*引用*有关,而不是与值本身有关。考虑`常量 foo = 42; foo 确实有作用 { method Str { '99' } }; 说 foo; #99`。虽然你可能(非常正确地)说我所做的只是改变了那个特定的“42”的方法,但关键是 Raku 还不支持真正的绝对不变性。
回答
另一种方式,使用多分派:
my $a := 6; # constant
my $b = 6; # variable
multi sub mutable($ is rw) { True }
multi sub mutable($) { False }
say mutable($a); # False
say mutable($b); # True
say mutable(42); # False