Как избежать импорта символов по умолчанию при использовании модуля? - PullRequest
8 голосов
/ 31 марта 2019

Я собираюсь использовать Hash::Merge в качестве примера.Рассмотрим:

use v6;
use Hash::Merge; # <-- imports all symbols marked with "is export" from Hash::Merge
my %hash1 = a1 => [1, 2, 3], b => "xxx", c => { ca => 1 }, e => 5;
my %hash2 = a1 => [1, 5, 3], b => "yyyy", c => { ca => 5, f => "a" }, d => 4;
my %res = merge-hash(%hash1, %hash2, :no-append-array);

Предположим, я не хочу загрязнять свое пространство имен при использовании модуля (здесь Hash::Merge используется в качестве примера).Я мог бы достичь этого в Perl 5, указав пустой список аргументов для use:

use Hash::Merge ();   # <-- No symbols will be imported into the current namespace

Затем я бы вызвал подпрограмму merge-hash, используя ее полностью определенное имя: Hash::Merge::merge-hash.

Согласно этому отчету об ошибке кажется, что это невозможно в Perl 6. Это правильно?

Ответы [ 2 ]

9 голосов
/ 31 марта 2019

Чтобы загрузить модуль без импорта, используйте need вместо:

need Hash::Merge;

В случае рассматриваемого модуля он не объявляет вещи, которые он экспортирует с our, что, к сожалению, означает, что он называется:

Hash::Merge::merge-hash(...)

Не будет работать, так как он не установлен в пакете. Тем не менее, все еще можно выкопать символ из экспорта вручную:

need Hash::Merge;
say Hash::Merge::EXPORT::DEFAULT::merge-hash({ a => 1 }, { b => 2 })

И, для большего удобства, он может быть псевдонимом:

need Hash::Merge;
my constant &merge-hash = &Hash::Merge::EXPORT::DEFAULT::merge-hash;
say merge-hash({ a => 1 }, { b => 2 });

Существует спекулятивный синтаксис по линиям use Hash::Merge :MY<&merge-hash>, который не реализован в текущих версиях Perl 6, но, вероятно, будет иметь ту же семантику, что и трюк constant, показанный здесь.

8 голосов
/ 31 марта 2019

Простой способ справиться с этим - просто поместить модуль в блок.

{ use Hash::Merge }

Поскольку {} определяет область действия, ничто не ускользает от нее.

Вы можете получить это так, чтобы что-то могло убежать, поместив это в do блок.

do { use Hash::Merge }

Что вы можете сделать, так это иметь это так, чтобы значения, которые вам нужны, сохранялись в правильных местах.

my &merge-hash = do { use Hash::Merge; &merge-hash }
my (&merge-hash,&merge-hashes) = do { use Hash::Merge; (&merge-hash, &merge-hashes) }

Другой вариант - просто разместить его в как можно меньшем объеме.

my %a = a => 1;
my %b = b => 2;

my %c;
{
  use Hash::Merge;
  %c := merge-hash %a, %b
}

или

my %c := do {
  use Hash::Merge;
  merge-hash %a, %b
}

(Оператор привязки := был использован только потому, что результат merge-hash уже является хешем.)

...