在分配Perl 6程序之前使用Perl 6程序中的变量

时间:2018-03-08 14:32:54

标签: perl6

我想用我的程序将文字分配给文件末尾的一些变量,但是要先使用这些变量。我提出的唯一方法是:

my $text;

say $text;

BEGIN {    
    $text = "abc";
}

是否有更好/更惯用的方式?

3 个答案:

答案 0 :(得分:5)

刚刚开始运作。

改为创建子程序:

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" };

为了避免这种情况,您可以将text设为term,这有效地使得text一词的行为与text()相同:

say text;        # "abc",    interpreted as: say text() 
say text ~ text; # "abcabc", interpreted as: say text() ~ text()

sub term:<text> { "abc" };

对于编译时优化和警告,我们还可以向其添加pure trait(感谢Brad Gilbert!)。 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" };

答案 1 :(得分:3)

与Perl 5不同,在Perl 6中,BEGIN不一定是块。但是,必须先查看词法定义才能使用它,因此BEGIN块必须在say之前完成。

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

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

答案 2 :(得分:3)

首先,重温一下你的问题:

  

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

发布例程

say foo;
sub foo { 'abc' }

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

因此,您可以使用例程,就好像它们是Christopher Bottom's answer中描述的变量一样。

首次使用时自动声明变量

strict是一个"pragma",用于控制P6编译器在解析尚未声明的以sigil开头的变量/常量时的反应。

P6启动严格模式开启的程序。这意味着编译器将坚持预先声明任何sigil'd变量/常量。 (通过预先声明,我的意思是在使用变量/常量之前出现文本显式声明。)

但是您可以编写use strictno strict来控制在给定的词法范围内是否打开或关闭严格编译指示,这样就可以了:

no strict;

say $text;

BEGIN {    
    $text = "abc";
}

警告no strict生效(不幸的是,大多数编程语言的工作方式)使得变量名称的意外拼写错误比使用use strict模式时更大的麻烦。

在与第一次使用

相同的语句中显式声明变量

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

say my $text;

BEGIN {    
    $text = "abc";
}

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

在运行时初始化

上面显示的BEGIN移相器在 compile -time(在my声明之后运行,这也发生在编译时,但在say之前,这是在运行时发生的。)

如果您想在运行时初始化变量/常量,请改用INIT

say my $text;

INIT {    
    $text = "abc";
}

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

使用正电子(ym)变量

鉴于对您的问题的字面解释,“positronic”或ym变量将是另一种解决方案。 (这个功能不是内置的。我之所以包括它,主要是因为我在回答这个问题之后遇到它并认为它属于这里,至少对娱乐价值而言。)

这种变量的初始化和计算从 last 语句开始使用它,并相对于代码的文本顺序向后发生。

这是几个疯狂的声音之一,但实际上工作和有用的概念,达米安“疯狂科学家”康威在他的2011年演讲中讨论在多个拓扑连接的量子 - 相对论并行空间时间的时间Quaquaversal虚拟纳米机器编程...制作简单!的。

以下是指向the bit where he focuses on these variables的链接。

(整个演示非常令人高兴,特别是如果你对物理学感兴趣;编程技巧;观看高度创造性的神童;和/或享受出色的演讲技巧和幽默。)

创建一个PS pragma?

就酷感而言,与我刚刚介绍的Damian的正电子变量特征相比,下面的情况相形见绌,但这是我在思考这个问题时的一个想法。

有人可能会实现类似下面的pragma:

use PS;

say $text;

BEGIN $text = 'abc';

PS将词法应用no strict,另外还需要避免编译时错误:

  • 自动声明的变量/常量必须与BEGININIT移相器中的帖子声明匹配;

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

相关问题