需求行为(静态+动态)[RAKU]

问题描述 投票:4回答:2

我的问题与require的行为有关,该行为与所需名称空间的静态或动态解析一起使用。

在我看来,require不是正常的子例程。

[当我们将require与文字(模块名称)结合使用时,将在编译时对require进行评估并执行(?)。

示例:

    my $response = ::('MODULE');  # this happens at runtime
    say $response.^name;          # printout: Failure # if MODULE doesn't exist (That means that the require was evaluated before the dynamic lookup, at complilation time)

    try require MODULE;           # this happens at compilation time (?)

当我们在动态查询中使用require时,动态查询的核心功能将在新的例程中进行代码转换/融合,该例程的行为与其部分和的总和不同。

就像我们将转换后的查询转换为增强的内容:

需要+动态查找=转换后的查找

示例:

try require ::($module);   # this happens at runtime

“动态查找”的正常行为是搜索现有的“命名空间”(或符号)。如果未找到,则返回“失败”对象。

需要增强的“动态查找”进行常规查找,如果未加载$ module,则在raku modules目录中进行“搜索”,如果找到,则进行加载,否则抛出异常。

这是所提供功能的准确描述吗?

lookup raku rakudo
2个回答
2
投票

在我看来require不是正常的子例程。

这不是子例程。

如果在the official doc中搜索它,您会看到它在常规参考部分中列出了不是,而是语言参考的模块部分。这是一条语句,是编译器可以理解的语言的特殊部分。

try require MODULE; # this happens at compilation time (?)

几乎所有动作都发生在运行时

Aafict在编译时发生的唯一一点是,编译器检查以查看MODULE是否已被声明为符号。如果还没有,则编译器会声明它,并将其绑定到一个刚为此require创建的空占位符包。

引用文档:

Arequire带有编译时符号

将安装占位符包...

Aiui它创建了一个占位符包,大概就是这样,如果在编译时分配或绑定了require的值,它会返回一些东西,但是如果它创建了一个占位符,则它仅绑定到编译时符号,并且仅当该符号不存在时才这样做。

try require ::($module); # this happens at runtime

正确。因此,与try require FOO情况不同,它在编译时从不创建任何符号。

“动态查找”的正常行为是搜索现有的“命名空间”(或符号)。如果未找到,则返回“失败”对象。

始终是[[动态查找

的行为,而不只是”正常行为”的行为。因此,::('jakar') 作为动态查找始终会查看当前程序是否动态地具有符号'jakar',并且是否没有返回Failure

但是在require ::('jakar')中,我不认为::('jakar')是动态查找,或者如果是这样,那就不重要了。我认为这只是动态符号插值,是动态

构造符号

的一种方式。
我不认为require试图查看该符号是否已声明,并且如果确实发生查找,它认为它会忽略返回的值。它只需要一个符号将被解释为程序包名称,然后它将尝试加载该符号。

加载成功后,它会创建一个匹配的符号-尽管如果本地词法作用域已经包含相同名称的符号,我还没找到去处;也许在这种情况下创建一个符号?

require增强的“动态查找”进行常规查找,如果未加载$module,则在raku modules目录中进行“搜索”,如果找到,则进行加载,否则抛出异常。

您是否能够复制[[not要求装入程序包的情况?require

(我可以想象,如果模块加载器知道它已经被加载,就不会费心地加载它。但是require本身是否参与了这一工作?肯定不会吗?)>

这是所提供功能的准确描述吗?

Afaik直到运行时都不会加载,无论require的参数是在编译时声明的静态标识符还是动态构造的包名称。

从您对这个答案的评论中:


普通动态查找例程的不同行为,它不会再进一步​​检查存储库(仅检查名称空间)

这似乎将符号与程序包加载混合在一起。

jakar和jakar不是同一个人! :)

require会在编译期间做一些事情。

require Module; say Module;
假定加载该模块将为您提供名称为Module的东西。

因此它将在编译时安装一个具有该名称的临时符号。

这是它在编译时所做的唯一事情。(所以当我说“某事”时我就轻打了。)

if Bool.pick { require module-which-does-not-exist; module-which-does-not-exist.method-call() }

[大约有一半的时间以上没有执行任何操作。另一半时间,它在运行时抱怨找不到模块。

((我选择了Bool.pick而不是False,因此编译时优化器肯定无法对其进行优化。)

当您使用标识符以外的名称进行调用时,它在编译时不知道模块将是什么。因此,它无法创建临时名称空间。

require 'Module'; say Module; # COMPILE ERROR: undeclared name


require Module; # RUNTIME ERROR: can't find 'Module' say Module;

require 'Module'; # RUNTIME ERROR: can't find 'Module' say ::('Module');

if False {
    require Module;
    say Module;
}
# no error at all
if False {
    require 'Module';
    say ::('Module');
}
# no error at all

0
投票
© www.soinside.com 2019 - 2024. All rights reserved.