BEGIN何时真正开始(或运行)?

时间:2018-12-18 18:27:49

标签: perl6 precompile

  

这与this issue in the Perl 6 documentation repo

有关

目前尚不清楚BEGIN blocks实际运行的阶段。文档说“编译时”,但是Perl已预编译,因此可能actually be precompile time。事实上,让我们使用此代码

unit module Beginner;

BEGIN {
    say "This is where all started";
}

从这里

require Beginner;

say "Begun";

在新目录中(运行rm -rf .precomp)。它输出:

This is where all started
Begun
  

到目前为止,已经创建了保存缓存的.precomp目录。

所以让我们从这里使用它:

use Beginner;
say "Already started";

它显然只返回Already started。 (如果我们运行第一个程序,也会发生同样的情况)。 这可能是一个问题,因为用户可能事先不知道是否会进行预编译,这反过来意味着不确定何时进行“编译时间”。无论如何,问题是:我们如何正确地表述它以在文档中进行解释?另外,是否应该鼓励使用BEGIN(因为计算出的值将被存储在预编译高速缓存中,从而有效地从运行时中删除)还是不鼓励使用JSShouldTerminateCallback?有一些很好的用例吗?

2 个答案:

答案 0 :(得分:8)

BEGIN发生在编译时,正如您所正确观察到的,这可能是预编译时。

只要您不认为脚本启动时会进行编译,我就不会发现任何问题。就像C ++模板是在编译时进行评估的,通常与执行时会有所不同。

  

此外,应该鼓励使用BEGIN(因为计算出的值将被存储在预编译高速缓存中,从而从运行时有效地消除)

应鼓励一切使用适当的用例,而不鼓励使用其他一切。

如果要在程序启动时运行某些程序,请使用INIT,而不要使用BEGIN

  

是否有一些很好的用例?

许多元编程可以(并且应该)在编译时完成,例如,基于固定的名称列表创建方法和属性的列表。在每个程序启动时这样做都是浪费,并且程序的其他部分在编译时可能需要完整的类型。

答案 1 :(得分:4)

莫里茨写了什么(你接受了)。

但是我想做个比喻。

  

我们如何正确制定公式以在文档中进行解释?

可能有一个类比。这是我头顶上的一个。也许这将有助于为该SO的读者澄清一些事情。在最后我要提到的方式上,这是十分可悲的。因此,请勿在文档中使用它。但这也许会有助于激发一个不错的类比,以添加到文档中。


程序就像蛋糕的食谱。在我们的类比中,它混合了准备和烘焙说明。

按照准备蛋糕的说明编译程序。

运行程序是按照将蛋糕放入烤箱并进行烘烤的说明进行操作。

预编译就像准备蛋糕并将其放在冰箱中待第二天烘烤一样。

BEGIN时间是准备时间。如果指令以BEGIN开头,那么在蛋糕准备过程中阅读食谱的人遇到该指令时,必须立即遵循该指令。

准备时间可以在烘烤蛋糕之前或前一天。

通常,主厨(编译器和使用编译器的人)选择的任何策略(准备并立即烘烤或准备,放入冰箱然后烘烤)的指令(程序)都必须能够正常工作。

  

是否应该鼓励使用BEGIN(因为计算出的值将存储在预编译高速缓存中,从而有效地从运行时中删除)还是不建议使用?

做好准备通常是一件好事。在大多数情况下,无论准备好的蛋糕在冰箱中存放一段时间还是准备后立即烘烤,准备烘烤蛋糕的工作都是相同的。

所以我要鼓励。当然不鼓励他们,至少通常不鼓励他们。

但是偶尔将一些可能被称为“准备工作”的工作推迟到烘烤开始之后才有意义。在这种情况下,请勿使用BEGIN,因为BEGIN在运行时之前 的意义上特别意味着编译时接下来。

  

是否有一些很好的用例?

常量是进行“准备”工作的理想选择。

代表2018年圣诞节的常量是在编译时进行定义的很好的选择。

代表圣诞节的常量可能是在运行时定义的一个很好的选择。

(Corny故意省略了烘烤圣诞蛋糕的讽刺意味。)


这个比喻很烂,因为一旦您烤了一个蛋糕(运行程序),准备好的蛋糕(预编译缓存项)就消失了。

烹饪某种东西的概念需要用一个涉及准备(编译)某种东西的过程来代替,然后可以将其复制任意次以使用它(运行它)。在解释有时在运行时应该如何进行“准备”时,还需要很好地进行类比。

如果该类比用于“ foo”(“编译”)和“ bar”(“运行”)事物(程序),则该类是否具有与所使用的工具称为“ fooer”相同的怪异度