代码之家  ›  专栏  ›  技术社区  ›  Eugene Barsky

在Perl 6程序中使用变量,然后再分配给它

  •  4
  • Eugene Barsky  · 技术社区  · 8 年前

    我想在程序中为文件末尾的一些变量分配文本,但要更早地使用这些变量。我想到的唯一方法是:

    my $text;
    
    say $text;
    
    BEGIN {    
        $text = "abc";
    }
    

    有更好/更惯用的方法吗?

    3 回复  |  直到 8 年前
        1
  •  5
  •   Elizabeth Mattijsen    6 年前

    只要发挥作用。

    改为创建子例程:

    say text();
    
    sub text { "abc" }
    


    更新(感谢raiph!纳入您的反馈,包括使用 term:<> ):

    在上面的代码中,我最初省略了调用的括号 text ,但始终包含它们会更易于维护,以防止解析器误解我们的意图。例如

    say text();          # "abc" 
    say text() ~ text(); # "abcabc"
    say text;            # "abc", interpreted as: say text()
    say text ~ text;     # ERROR, interpreted as: say text(~text())
    
    sub text { "abc" };
    

    为了避免这种情况,您可以 文本 term ,这实际上使 文本 行为与相同 text() :

    say text;        # "abc",    interpreted as: say text() 
    say text ~ text; # "abcabc", interpreted as: say text() ~ text()
    
    sub term:<text> { "abc" };
    

    对于编译时优化和警告,我们还可以添加 pure trait 感谢布拉德·吉尔伯特(BradGilbert!)。 is pure 断言对于给定的输入,函数 "always produces the same output without any additional side effects" :

    say text;        # "abc",    interpreted as: say text() 
    say text ~ text; # "abcabc", interpreted as: say text() ~ text()
    
    sub term:<text> is pure { "abc" };
    
        2
  •  3
  •   Elizabeth Mattijsen    8 年前

    与Perl 5不同,在Perl 6中 BEGIN 不必是块。但是,必须先查看词法定义,然后才能使用它,因此 开始 必须在 say

    BEGIN my $text = "abc";
    say $text;
    

    不确定这是否构成对您问题的回答。

        3
  •  3
  •   Community Mohan Dere    6 年前

    首先,重新表述您的问题:

    有哪些选项可以简洁地引用其初始化代码在同一源文件中显示得更远的变量(或常量等)?

    后声明例程

    say foo;
    sub foo { 'abc' }
    

    当P6编译器解析 identifier 那已经 sigil ,它检查是否已经看到该标识符的声明。如果没有,则假定标识符对应于一个例程,该例程稍后将被声明为“listop”例程(它接受零个或多个参数),然后继续。(如果其假设被证明是错误的,则编译失败。)

    因此,您可以将例程当作变量来使用,如中所述 Christopher Bottom's answer

    首次使用时自动声明变量

    strict 是一个 "pragma" 它控制P6编译器在解析以 西格尔

    P6在严格模式打开时启动程序。这意味着编译器将坚持预先声明任何sigil'd变量/常量。(我所说的预折旧是指 明确的 出现的声明 文字上 使用变量/常量之前。)

    但你可以写 use strict no strict 要控制严格pragma在给定的词法范围内是打开还是关闭,这将起作用:

    no strict;
    
    say $text;
    
    BEGIN {    
        $text = "abc";
    }
    

    警告 拥有 无严格要求 事实上(不幸的是,大多数编程语言都是这样工作的)使得变量名的意外拼写错误比实际情况更令人讨厌 使用严格的 模式打开。

    在第一次使用时在同一语句中显式声明变量

    您不必将声明作为单独的语句编写。您可以声明 在同一语句或表达式中使用变量:

    say my $text;
    
    BEGIN {    
        $text = "abc";
    }
    

    警告 如果你重复 my $bar 完全相同 在词法范围内,编译器将发出警告。相反 say my $bar = 42; if foo { say my $bar = 99 } 创建两个不同的 $bar 无警告的变量。

    在运行时初始化

    这个 BEGIN 上图所示的相位器在以下位置运行 编写 -时间(在 my 声明,这也发生在编译时,但在 say ,在运行时发生)。

    如果要在运行时初始化变量/常量,请使用 INIT 而是:

    say my $text;
    
    INIT {    
        $text = "abc";
    }
    

    初始化 代码在任何其他运行时代码之前运行,因此初始化仍然发生在 执行。

    使用正电子( ym )变量

    对你的问题给出了字面上的解释“正电子”或 ym公司 变量将是另一种解决方案。(这个功能不是内置的。我之所以包括它,主要是因为我在回答这个问题后遇到了它,并且认为它属于这里,至少是出于娱乐价值。)

    此类变量的初始化和计算从 最后的 语句,并相对于代码的文本顺序向后出现。

    这是Damian“疯狂科学家”Conway在2011年的演讲中讨论的几个听起来很疯狂但实际上很有用的概念之一 多拓扑连接量子相对论并行时空中的时间准通用虚拟纳米机编程。。。变得简单!

    这里有一个链接 the bit where he focuses on these variables

    (整个演讲都很有趣,尤其是如果你对物理、编程技术、观看极具创造力的神童以及/或欣赏出色的演讲技巧和幽默感感兴趣的话。)

    创建 PS 布拉格语?

    就冷静而言,以下内容与我刚刚介绍的Damian的正电子变量功能相比相形见绌,但这是我在思考这个问题时的想法。

    可能有人会实现如下pragma:

    use PS;
    
    say $text;
    
    BEGIN $text = 'abc';
    

    附言 将在词汇上应用 无严格要求 此外,为了避免编译时错误,还需要:

    • 自动声明的变量/常量必须与 开始 初始化 移相器;

    • 如果变量/常量的第一次使用(文本上)不是绑定或赋值,则声明必须包括初始化。