Как Perl6 решает, какая версия модуля загружается? - PullRequest
8 голосов
/ 14 апреля 2019

Когда я делаю use Foo:ver<1.0>;, он загружает версию 1.0 модуля Foo. Но что происходит, когда я делаю use Foo;?

1 Ответ

10 голосов
/ 14 апреля 2019

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

Префикс 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

Предположим следующее:

  • 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>, самая высокая версия API Foo:api<1>:ver<0.1> и, следовательно, выбрана.


3-йто, что определяет, какая версия модуля загружается, это поле auth.В отличие от api и ver это не подразумевает никакой сортировки.А также, в отличие от полей api и ver, вы, вероятно, не должны использовать его в своем примере, например, 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 полностью игнорируется).


Для получения дополнительных примеров хорошими источниками являются тесты спецификаций .

...