【问题标题】:Unbind or undefine a variable in raku取消绑定或取消定义 raku 中的变量
【发布时间】:2020-10-22 15:22:31
【问题描述】:

阅读 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

那么赋值和绑定有什么区别呢?
如何取消定义变量?

【问题讨论】:

    标签: raku rakudo


    【解决方案1】:

    这里有很多不同的问题要讨论。

    > my $k := 5;
    > $k := Nil;
    Cannot use bind operator
    

    第一个问题是 Raku REPL。 cf你的最后一个SO。你试过CommaIDErepl.it吗?

    您的代码完全有效:

    my $k := 5;
    $k := Nil;
    say $k; # Nil
    

    继续:

    my $k := 5;
    $k = Nil;
    Cannot assign to an immutable value
    

    这是不同的。在将5 绑定到$k 之后,$k = Nil 代码会尝试将值分配数字中。只有容器[1]支持assignment。数字不是容器,因此您不能分配给它。


    澄清您提到但未明确涵盖的一些案例:

    my @foo;
    @foo := Nil;
    Type check failed in binding; expected Positional...
    

    虽然标量变量(带有$ sigil 的变量)将绑定到任何值或容器,但@ sigil 的变量将仅绑定到Positional 容器,例如Array。 (同样是 %Associative,例如 Hash。)

    不仅如此,这些容器总是被定义的。所以即使它们是空的,它们仍然会为.defined 返回True

    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)]
    

    如果@ sigil'd 变量的声明没有将其绑定到某个显式的Positional 类型,则它会绑定到@ 变量的默认 选项。这是一个Array,默认元素值为Any

    上面的@foo = Nil; 语句分配 Nil@foo 的第一个元素。将值赋值到多元素容器的不存在元素意味着新的Scalar 容器弹出存在并在赋值继续之前绑定到该缺失元素。然后,因为我们分配了一个Nil,并且因为Nil 表示一个值的缺失,所以Array 的默认值((Any))被复制到Scalar 而不是 Nil


    关于sub 案例...

    sub foo {}
    &foo = {}  # Cannot modify an immutable Sub (&foo)
    &foo := {} # Cannot use bind operator ...
    

    虽然sub foo 声明会生成&amp;foo 标识符,但它故意既不可分配也不可绑定。如果你想要一个Callable 变量,你必须使用普通变量声明来声明一个。


    取消绑定或取消定义变量

    您不能取消绑定变量,让它们完全不受任何约束。 (换句话说,Raku 避免了the billion dollar mistake。)在某些情况下,您可以重新绑定变量。

    在某些情况下,您可以将未定义的值绑定或分配给变量。如果它不是标量变量,那么就像上面提到的 @ 变量示例一样。接下来考虑标量情况。

    绑定案例示例:

    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; 行。

    say $foo.WHAT; 行中,Scalar 保持隐藏状态。相反,我们看到的是(Any)。但是(Any) 的类型,该值在内部 绑定到$fooScalar 容器中。

    在下一行中,我们开始通过在$foo 上调用.VAR.WHAT 来揭开面纱。 .VARScalar 显示自己,而不是产生它包含的 value。所以我们看到了Scalar这个类型。

    但如果你在那个Scalar 上调用.defined,它仍然坚持隐藏!:

    my $foo;
    say $foo.VAR.defined;  # False
    say $foo.VAR.DEFINITE; # True
    

    (迫使 Raku 告诉你关于其确定性观点的最终真相的唯一方法是调用确定性的最终仲裁者,.DEFINITE。)

    那么规则是什么?

    如果根据原始变量声明这样做是有效的,编译器将允许您将给定的新值或容器分配或绑定到变量。

    分配或绑定未定义的值遵循相同的规则。

    绑定

    所有变量必须在其声明的末尾绑定。

    如果一个变量的声明允许一个未定义的被绑定/赋值给那个变量,那么这个变量在这个意义上可以是未定义的。但在所有其他情况和意义下,变量本身永远不能“未绑定”或“未定义”。

    绑定就是让一个变量对应一些容器

    • 带有@% 符号的变量必须绑定到容器(默认分别为ArrayHash)。

    • 带有$ 标志的变量必须绑定到容器(默认为Scalar)或值。

    • 带有&amp; 标记的变量必须绑定到Callable 值或Scalar 约束为包含Callable 值。 (声明 sub 后可见的 &amp; sigil 变量不允许重新绑定或赋值。)

    作业

    赋值意味着复制一个值一个容器。

    如果一个变量绑定到一个容器,那么你可以给它赋值,前提是编译器根据原始变量声明允许赋值。

    如果变量没有绑定到容器,那么编译器将拒绝对它的赋值。

    标量变量

    如果您使用标量容器,就好像它是一个,那么您将获得保存在容器内部的值。 p>

    绑定一个值(已定义或未定义)到一个标量变量将意味着它将停止充当容器。如果您然后尝试分配给该变量,它将不起作用。您需要将其重新绑定回容器。

    脚注

    [1] 在这个答案中,我使用了“容器”这个词来指代任何可以用作包含其他值的容器的值。例如,ArrayHashScalar 的实例。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-01-01
      • 2018-09-12
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多