【发布时间】:2019-01-06 21:54:00
【问题描述】:
假设我想在编译时创建一些类型,但在此之前,让我们用一个更简单的例子来测试编译时代码:
# in file root.pm6
sub foo($a) { $a.say }
sub EXPORT {
# Things here may be a lot more complex
foo 1;
foo 2;
foo 1;
%( one => 1 )
}
以及直接原始库和最终用户文件之间的模块:
# in file middle.pm6
use root;
class A {} # Do something with stuff from root.pm6
最终用户文件:
# in file user.pm6
use middle;
然后在命令行中:
➜ tester perl6 -I. user.pm6
1
2
似乎对foo 的第三次调用已被缓存,第三次没有执行。
这种行为使得sub EXPORT(以及其他编译时区域)中任何相对复杂的计算(基于代码重用)变得不可能。
根据我的理解,编译时代码意味着正常执行,其结果(例如一些声明、调整等)可由其他模块从编译单元访问。但是,也涉及到某种缓存。
问题最终是“如何实现我想要的”以及可能的里程碑:
1)这种缓存是有意的吗?
2)如果是,是否可以在具有编译时代码执行优势的同时禁用它?如果不是,还有哪些可能的解决方法?
更新 1:更具体地解释我想要的东西:在编译时,我正在解析一个配置文件并创建要导出的类型。我希望那些被预编译,这就是重点。类型可以嵌套并且各种情况都是可能的,所以我提交了一个过渡状态机模拟,它实现为一个简单的子例程,带有很长的given-where 语句,一些分支是递归的(底部总是存在的)。我坚持的问题是某些分支在被解雇一次后不会被执行,我可以打出简单的双 foo 1 电话我在主要问题中提出。
更新 2:如 raiph 所述,当原始库和用户一之间的间接级别为 0 时,从命令行运行时它可以正常工作,但当结构为 root lib file that creates types -> middleware lib file that patches those -> end-user(be it a test file or another module 时,并非所有代码都被执行。
【问题讨论】:
-
我只阅读了你的问题的标题而不是它的正文。所以这可能没用,但你见过
no precompilation;吗?另请参阅Constants are computed at compile time。 -
至于那两个: 1) 事实上,我想要 东西被预编译,这是我工作的重点。 2)至于常量 - 是的,但我不确定它是否相关。
-
@Takao 我看不出“预编译”和“缓存”之间的区别。预编译在(默认)
.precomp目录中创建一个预编译缓存。如果你想测试编译它们,你可以使用 perl6 -c,但这也意味着预编译。也许您应该考虑使用不同的移相器而不是 EXPORT,尽管我知道您希望导出变量,但是有不同的方法可以实现。 -
我刚刚在 REPL 之外尝试了您的代码并得到了
121,即它按我的预期工作。 -
确实如此。但是,当间接级别超过 2(即 lib -> lib -> lib)时,它不会像这样工作,第一个使用预编译。我会更新问题。
标签: raku