Perl6如何决定加载哪个版本的模块?

uge*_*exe 8 versioning module package perl6 api-versioning

当我这样做时use Foo:ver<1.0>;,将加载模块的1.0版本Foo。但是,当我这样做时会发生什么use Foo;呢?

uge*_*exe 10

TL; DR:如果未指定特定版本,则默认的Perl6安装将从CompUnit::Repository与该模块的任何版本相匹配的第一个版本开始加载最新版本(不一定是最高版本CompUnit::Repository)。


CompUnit::Repository除非另有说明,否则可以创建和加载本身仅加载模块的随机版本的非内核。该答案不适用于这些,而是​​将重点放在各种核心的CompUnit::Repository行为方式和特定方式上。

确定要加载哪个模块的第一件事是哪个首先CompUnit::Repository匹配请求的标识。默认的存储库链如下所示:

# EXAMPLE 1

$ perl6 -e '.say for $*REPO.repo-chain'
inst#/home/ugexe/.perl6
inst#/home/ugexe/perl6/install/share/perl6/site
inst#/home/ugexe/perl6/install/share/perl6/vendor
inst#/home/ugexe/perl6/install/share/perl6
Run Code Online (Sandbox Code Playgroud)

inst#前缀告诉我们,这是一个CompUnit::Repository::Installation。这是相关的,因为这样的回购协议可以包含多个分布-包括同分布的多个版本-这是不是单分布的真实CompUnit::Repository::FileSystem使用-I.-Ilib(这是真正的 -Ifile#/home/ugexe/repos/Foo-Ifile#/home/ugexe/repos/Foo/lib)。

# EXAMPLE 2

$ perl6 -I. -e '.say for $*REPO.repo-chain'
file#/home/ugexe/repos/Foo
inst#/home/ugexe/.perl6
inst#/home/ugexe/perl6/install/share/perl6/site
inst#/home/ugexe/perl6/install/share/perl6/vendor
inst#/home/ugexe/perl6/install/share/perl6
Run Code Online (Sandbox Code Playgroud)

让我们假设以下内容:

  • file#/home/ugexe/repos/Foo 包含 Foo:ver<0.5>

  • inst#/home/ugexe/.perl6包含Foo:ver<0.1>Foo:ver<1.0>

  • inst#/home/ugexe/.perl6包含Foo:ver<2.0>Foo:ver<0.1>

use Foo; 将加载:

  • 例1 - Foo:ver<1.0>inst#/home/ugexe/.perl6

  • 例2 - Foo:ver<0.5>file#/home/ugexe/repos/Foo

即使所有存储库中最高的版本是Foo:ver<2.0>链中与Foo(即)胜出的任何版本均匹配的第一个存储库use Foo,所以Foo:ver<2.0>永远不会选择它。您可能会猜到,这使“最高版本”成为确定要加载模块版本的第二件事,但这实际上是第四!但是,我在这里提到了它,因为对于典型用法而言,这已经足够了。


确定要加载哪个版本的模块的第二件事是该api字段。本质上,这是另一个版本字段,当与版本本身结合使用时,它提供了固定主要版本的基本方法。

让我们假设以下内容:

  • file#/home/ugexe/repos/Foo 包含 Foo:api<0>:ver<0.5>

  • inst#/home/ugexe/.perl6包含Foo:api<1>:ver<0.1>Foo:api<0>:ver<1.0>

use Foo; 将加载:

  • 例1 - Foo:api<1>:ver<0.1>inst#/home/ugexe/.perl6

  • 例2 - Foo:api<0>:ver<0.5>file#/home/ugexe/repos/Foo

即使在示例1中,最高版本是Foo:api<0>:ver<1.0>Foo:api<1>:ver<0.1>因此也选择了最高api版本。


确定要加载哪个版本的模块的第三件事是该auth字段。不像apiver它并不意味着任何排序。而且与领域不同apiver您可能不应该在自己的实例中使用它use Foo-它以策略为中心,并且将成为大多数开发人员不必担心(ab)使用的强大工具/逃生途径。

让我们假设以下内容:

  • file#/home/ugexe/repos/Foo 包含 Foo:auth<github:ugexe>:ver<0.5>

  • inst#/home/ugexe/.perl6包含Foo:ver<0.1>Foo:auth<github:ugexe>:ver<1.0>

use Foo; 将加载:

  • 例1 - Foo:auth<github:ugexe>:ver<1.0>inst#/home/ugexe/.perl6

  • 例2 - Foo:auth<github:ugexe>:ver<0.5>file#/home/ugexe/repos/Foo

在这两个示例中,use Foo;都是相同的use Foo:auth(*):ver(*),因此即使回购假设之一包含一个不带模块的模块,auth这也不意味着它与完全匹配use Foo;。而是将:auth(*)任何auth值都包含为匹配项(有效含义auth将被完全忽略)。


有关更多示例,规格测试是一个很好的来源

  • @raiph是正确的,我为auth添加了一个示例。我试图避免的是解释如何使用auth。它更着重于策略,将成为大多数开发人员应该永远不必担心滥用的强大工具。 (2认同)