禁止无符号变量重新绑定是否有目的或好处



在试图更好地理解无符号变量以及它们与$符号变量的区别时,我发现,与$符号变量不同,无符号变量在初始化后无法反弹:

my $a = 42;
my $b := $a;
$b := 42;       # No exception generated
my c := $a;
c := 42;        # OUTPUT: «Cannot use bind operator with this left-hand side␤»

这是设计使然吗? 如果是这样,在不禁止无符号变量重新绑定的情况下$禁止无符号变量重新绑定是否有目的或好处?

是的,这肯定是设计使然,而且 - 就像Perl(6)设计中的大多数东西一样 - 这样做的原因不止一个。

在讨论无符号符号语法之前,值得花点时间回忆一下符号在语言中扮演的一些角色。其中包括:

  • 语法消歧(您可以随意调用变量,即使碰巧存在具有该名称的关键字)
  • 可读性(由于符号,程序中的数据脱颖而出)
  • 定义赋值语义(在Perl 6中赋值意味着"复制到",因此my @a = @b意味着迭代@b并将其中的每个东西放入@a中,因此将来任何对@b赋值都不会影响@a)
  • 限制可以绑定在那里的内容(例如,仅Positional@的东西)
  • $的情况下,控制将被视为单个项目的内容
  • @签名参数的情况下,导致缓存传入Seq

因此,每个符号都带有一组有用的默认行为,用于被视为单个项目($),位置索引(@),使用键索引(%)以及可以调用的数据(&)。在赋值、低级绑定和签名绑定的上下文中,它们中的每一个都带有通常所需的此类数据的语义。

这很好,直到想要编写针对所有这些行为的多态代码,或者不提交任何符号行为。Perl 6语言设计的早期迭代有类似sub foo($x is parcel) { }的东西,其中is parcel的东西实际上意味着"不要对此强加任何符号语义",除了这相当令人困惑,因为这个东西有$符号,但被选择退出语义。人们意识到,如果符号行为不适用,那么如果它看起来不同会更好("不同的东西应该看起来不同"的设计原则,这也在 Perl 中反复出现)。看起来不同的最明显方式是...没有印记。

但是,出于语法原因,签名中需要一些东西来消除从类型引入的名称(因为像(Foo)这样的签名在类型上匹配Foo但忽略值已经得到支持,并且很有用,我们不想失去它)。被选中扮演这个角色,得到sub foo(x) { },然后允许在子程序内部使用x

我的记忆是,在my的情况下允许这种形式是后来才出现的,尽管我不完全确定这一点。关于无符号符号不提交行为的重要一点是,它也不会提交赋值行为,因此对它的=更晚绑定(在可能的情况下,编译器会考虑符号,并为$/&@/%赋值发出完全不同的代码)。当然,如果符号绑定到一个值,则无法分配。

这就留下了绑定行为的问题。决定使无符号符号形成"静态单一赋值"语法,如其他答案之一所述。造成这种情况的原因有很多,包括:

  • 帮助保持符号的"数据突出"可读性属性,至少确保任何要(立即)可变的东西仍然带有符号
  • 还可以通过具有一种形式来增强程序的可读性,该表单让读者知道该符号永远不会重新绑定到新值,因此可以有效地将其视为范围内的常量。这与在没有符号的情况下很容易声明真正的constant是一致的。
  • 温和地鼓励一种更实用的风格(也许通过让那些决定讨厌符号的人用至少比符号提供的不同方式更具可读性的代码来回报我们其他人:-))

最后,我要指出的是,我发现术语"无符号变量"有点误导,因为它没有任何变量。它是一种语法,用于引入绑定到特定事物的初始化符号,并且始终在该符号的(词汇)生命周期内。考虑它们的最好方法可能是将它们与变量(这意味着存储)区分开来,而只是将它们视为将名称附加到值的一种方式。

无符号变量具有静态单一赋值语义。

优化机会优势

引用上述链接的 SSA 页面的"福利"部分:

SSA 的主要用途在于它如何通过简化变量的属性来同时简化和改进各种编译器优化的结果。例如,考虑这段代码:

y := 1
y := 2
x := y

人类可以看到,第一个赋值是没有必要的,第三行用y的值来自于y的第二个赋值。程序必须执行达到定义分析才能确定这一点。但是,如果程序采用 SSA 形式,则这两种情况都是即时的:

y1 := 1
y2 := 2
x1 := y2

通过使用 SSA 启用或强烈增强的编译器优化算法包括 [一长串可用的优化]。

因此,原则上,通过使用无符号变量编写代码,您可以为编译器提供更多优化机会。

人类推理的好处

一般来说,在P6中,变化的事物有一个符号,反之亦然,而没有,没有,反之亦然。从这个角度来看,禁止重新绑定是有意义的。

(出于这个原因,我倾向于认为将无符号变量绑定到容器,正如我在对您的问题的评论中所展示的那样,尤其是绑定到Scalar容器,是一种可疑的做法。

相关内容

最新更新