如何解决取消绑定或取消定义raku中的变量
在阅读Raku文档后,我仅发现this是未定义变量,我相信Raku在赋值=
和绑定:=
之间有区别
因此,定义和取消定义标量很容易:
> my $n
(Any)
> $n.defined
False
> $n = 3
3
> $n.defined
True
> $n = Nil
(Any)
> $n.defined
False
但是当绑定变量时,这是不可能的
> my $k := 5
5
> $k := Nil
===SORRY!=== Error while compiling:
Cannot use bind operator with this left-hand side
at line 2
------> <BOL>⏏<EOL>
> $k = Nil
Cannot assign to an immutable value
in block <unit> at <unknown file> line 1
但是对于数组或哈希,我可以将其清空,但仍定义变量。
对于函数,当您使用sub定义函数时,您不能取消定义它,但是作为匿名函数,您可以:
> my &pera = -> $n { $n + 2}
-> $n { #`(Block|140640519305672) ... }
> &pera = Nil
(Callable)
> &pera.defined
False
> my &pera = -> $n { $n + 2}
-> $n { #`(Block|140640519305672) ... }
> &pera = Nil
(Callable)
> &pera.defined
False
> sub foo ($n) { $n + 1}
&foo
> &foo.defined
True
> &foo = Nil
Cannot modify an immutable Sub (&foo)
in block <unit> at <unknown file> line 1
那么赋值和绑定之间有什么区别,以及我如何取消定义变量
解决方法
很多不同的问题在这里讨论。
> my $k := 5;
> $k := Nil;
Cannot use bind operator
第一个问题是Raku REPL。 cf您的最后一个SO。您是否尝试过CommaIDE或repl.it?
您的代码完全有效:
my $k := 5;
$k := Nil;
say $k; # Nil
继续前进:
my $k := 5;
$k = Nil;
Cannot assign to an immutable value
这是不同的。将5
绑定到$k
之后,$k = Nil
代码正在尝试将值分配到 number 中。仅容器 [1] 支持分配。数字不是容器,因此您无法分配给它。
澄清您提到但未明确涵盖的一些情况:
my @foo;
@foo := Nil;
Type check failed in binding; expected Positional...
虽然标量变量(带有$
标记的变量)将绑定到任何值或容器,但是@
标记的变量将仅绑定到{{1} {1}}。 (就像Positional
到Array
之类的%
。)
不仅如此,而且始终定义这些容器。因此,即使它们为空,它们仍然为Associative
返回Hash
:
True
现在将.defined
分配给数组:
my @foo := Array.new; # An empty array
say @foo.elems; # 0 -- zero elements
say @foo.defined; # True -- despite array being empty
如果Nil
标记变量的声明未将其绑定到某些显式my @foo;
@foo = Nil;
say @foo; # [(Any)]
类型,则将其绑定到{{的 default 1}}变量。这是@
,其默认元素值为Positional
。
上方的@
语句为赋值{em> 到Array
的第一个元素中。将值赋值放入多元素容器的不存在元素中,意味着会出现一个新的Any
容器并绑定到该缺失元素,然后继续分配。然后,由于我们正在分配@foo = Nil;
,并且因为Nil
表示值的不存在,因此@foo
的默认值({{ 1}})复制到Scalar
而不是Nil
。
在Nil
情况下...
Array
尽管(Any)
声明生成一个Scalar
标识符,但它既不是可分配的也不是可绑定的。如果要使用Nil
变量,则必须使用普通变量声明来声明一个变量。
取消绑定或取消定义变量
您不能 un 绑定变量,以使它们完全不受约束。 (换句话说,Raku避免使用the billion dollar mistake。)在某些情况下,您可以重新绑定变量。
在某些情况下,您可以将未定义的值绑定或分配给变量。如果它不是标量变量,则类似于上面介绍的sub
变量示例。接下来考虑标量情况。
绑定案例的示例:
sub foo {}
&foo = {} # Cannot modify an immutable Sub (&foo)
&foo := {} # Cannot use bind operator ...
稍后我们将了解sub foo
的含义。
分配案例:
&foo
重要的是要理解,在这种情况下,Callable
绑定到@
,这是一个容器,最肯定是“定义的”,对于某些“定义的”定义,尽管有外观my $foo := Any;
say $foo.defined; # False
say $foo; # (Any)
say $foo.VAR.WHAT; # (Any)
行中与此相反。
在.VAR
行中,my $foo = Any;
say $foo.defined; # False
say $foo.WHAT; # (Any)
say $foo.VAR.WHAT; # (Scalar)
保持隐藏状态。相反,我们看到了$foo
。但是Scalar
是绑定到say $foo.defined;
的{{1}}容器内 内值的类型。
在下一行中,我们通过在say $foo.WHAT;
上调用Scalar
来刺穿面纱。 (Any)
获取(Any)
来显示自己,而不是产生它包含的值。这样我们看到了类型Scalar
。
但是,如果您在$foo
上调用.VAR.WHAT
,它 still 坚持要隐藏!:
$foo
(强迫Raku告诉您有关其确定性观点的最终真理的唯一方法是将最终确定性仲裁者称为.VAR
。)
那么规则是什么?
如果根据原始变量声明有效,则编译器将允许您将给定的新值或容器分配或绑定到变量。
分配或绑定未定义的值遵循相同的规则。
绑定
所有变量必须在其声明的末尾绑定。
如果变量的声明允许将未定义的值绑定/分配给该变量,则从该意义上说,该变量可以是未定义的。但是在所有其他情况下,变量本身永远不能是“未绑定”或“未定义”的。
绑定是关于使变量对应于某些容器或值:
-
带有
Scalar
和Scalar
标记的变量必须绑定到容器(分别为默认.defined
和Scalar
)。 / p> -
带有
my $foo; say $foo.VAR.defined; # False say $foo.VAR.DEFINITE; # True
标记的变量必须绑定到容器(默认为.DEFINITE
)或值。 -
带有
@
标记的变量必须绑定到%
值或约束为包含Array
值的Hash
。 (由于声明了$
而可见的Scalar
标记变量不允许重新绑定或赋值。)
任务
赋值意味着将值复制到容器中。
如果将变量绑定到容器,则可以分配给它,前提是编译器根据原始变量声明允许分配。
如果变量未未绑定到容器,则编译器将拒绝对其的赋值。
标量变量
如果您使用标量容器作为它的值,那么您将得到保存在容器中的值。 >
将绑定到标量变量的值(已定义或未定义)将意味着它将停止充当容器。如果您随后尝试分配给该变量,它将无法正常工作。您需要将其重新绑定到容器。
脚语
[1] 在这个答案中,我使用了“容器”一词来指代任何可以用作包含其他值的容器的值。例如,&
,Callable
或Scalar
的实例。
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。