BEGIN 什么时候真正开始(或者是 运行)?

When does BEGIN actually start (or is run)?

This is related to this issue in the Perl 6 documentation repo

BEGIN blocks are actually run. Documentation says "compile time", but Perl is precompiled, so that might 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

By now, the .precomp directory that holds the cache has already been created.

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

use Beginner;
say "Already started";

显然 returns 只是 Already started。 (如果我们 运行 第一个程序也会发生同样的情况)。 这可能是个问题,因为用户可能事先不知道预编译是否会发生,这反过来意味着不确定 "compile time" 何时发生。无论如何,问题是:我们如何才能正确地表述它以在文档中对其进行解释?此外,应该鼓励使用 BEGIN(因为那里计算的值将存储在预编译缓存中,从而有效地从 运行 时间中消除)还是不鼓励?这有什么好的用例吗?

BEGIN 发生在编译时,如您所见,这可能是预编译时间。

我认为这没有任何问题,只要您不假设编译发生在脚本启动时。就像 C++ 模板在编译时求值一样,这通常与执行时有很大不同。

Also, should the use of BEGIN be encouraged (since values computed there are going to be stored in the precompilation cache and thus effectively eliminated from runtime) or discouraged

一切都应该因其适当的用例而受到鼓励,而对于其他一切都不鼓励。

如果你想在程序启动时运行一些东西,使用INIT,而不是BEGIN

Is there some good use case for this?

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

Moritz 写的内容(您接受了)。

但我想编一个比喻。

how can we formulate this correctly to explain it in the documentation?

可能打个比方。这是我头脑中的一个。或许这有助于为本 SO 的读者澄清一些事情。我将在最后提到的方式严重不足。所以不要在文档中使用它。但也许它会有助于激发一个像样的类比来添加到文档中。


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

编译程序就是按照准备蛋糕的说明去做。

运行一个程序正在按照说明将蛋糕放入烤箱烘烤。

预编译就像准备了一块蛋糕,放在冰箱里改天烤。

BEGIN时间为准备时间。如果指令以 BEGIN 开头,则在准备蛋糕期间阅读食谱的人一遇到该指令就必须遵循该指令。

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

通常情况下,无论厨师(编译器和使用编译器的人)选择哪种策略(准备并立即烘烤或准备,放入冰箱,稍后烘烤),指令(程序)都需要正常工作。

Also, should the use of BEGIN be encouraged (since values computed there are going to be stored in the precompilation cache and thus effectively eliminated from runtime) or discouraged?

做好准备通常是一件好事。很多时候,无论做好的蛋糕是在冰箱中存放一段时间,还是刚做好后立即烘烤,准备烘烤的蛋糕所要做的工作都是一样的。

所以我想说鼓励。肯定不会有勇气,至少一般不会

但有时将一些可能称为 "preparation" 的工作推迟到烘焙开始后才有意义。在这种情况下,不要为此使用 BEGIN,因为 BEGIN 之前 运行 的意义上特别意味着 编译时间 -time,如下所述。

Is there some good use case for this?

常量很适合作为 "preparation" 的一部分进行排序。

表示 2018 年圣诞节的常量很适合在编译时定义。

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

(关于烤圣诞蛋糕的老生常谈故意省略了。)


这个类比很糟糕,因为一旦你烤了蛋糕(运行 一个程序),准备好的蛋糕(预编译缓存条目)就不见了。

烹饪东西的概念需要用一个过程来代替,这个过程涉及准备(编译)一些东西,然后可以复制任意次数以使用它(运行)。它还需要很好地类比,以解释有时 "preparation" 应该如何在 运行 时间发生。

如果类比与使用的工具被称为 "fooer" 具有相同的古怪之处,则加分,即使它同时用于 "foo"("compile")和 "bar" ("run") 东西(程序)。