Получить значение символа по его имени в подпрограмме - PullRequest
0 голосов
/ 04 февраля 2019

Я делаю пакет, в котором я должен получить значение символа по его имени в подпрограмме, в то время как символ определен вне подпрограммы.

Вот упрощенный код, он работает, как и ожидалось

#! /usr/bin/env perl6 

sub dump_value($symbol) {
    say ::("$symbol")
}

# usage:
my $x = 10;
dump_value('$x');

# expected output: 10
# actual output: 10

Затем я поместил «dump_value» в отдельный файл, как показано ниже:

# somelib.pm6
unit module somelib;

sub dump_value($symbol) is export {
    say ::("$symbol")
}
# client.pl6
#! /usr/bin/env perl6

use lib ".";
use somelib;

my $x = 10;

dump_value('$x');

Компилятор пожаловался:

No such symbol '$x'
  in sub dump_value at xxx/somelib.pm6 (somelib) line 3
  in block <unit> at ./client.pl6 line 8

некоторые эксперименты.Ни один из них не удалось.

say ::("MY::$symbol")

say ::("OUR::$symbol")

say ::("OUTER::$symbol")

say ::("CLIENT::$symbol")
...

Так как исправить код?

ОБНОВЛЕНИЕ:

Спасибо!CALLERS::($symbol) решил мою первоначальную проблему.Но в несколько более сложной ситуации компилятор снова пожаловался:

# somelib.pm6
unit module somelib;

sub dump_value(@symbols) is export {
    # output: 6
    say CALLERS::('$x');

    # error: No such symbol 'CALLERS::$x'    
    say @symbols.map({ CALLERS::($^id) } ) 
}

# client.pl6
#! /usr/bin/env perl6

use lib ".";
use somelib;

my $x = 6;
my $y = 8;

dump_value(<$x $y>);

ОБНОВЛЕНИЕ СНОВА:

использование OUTER::CALLERS::($^id).

ОБНОВЛЕНИЕ СНОВА И СНОВА:

После того, как я поместил «dump_value» в другую подпрограмму, он больше не работал!

# somelib.pm6
unit module somelib;

sub dump_value(@symbols) is export {
    say @symbols.map({ OUTER::CALLERS::($^id) } )
}

sub wrapped_dump_value(@symbols) is export {
    dump_value(@symbols)
}
#! /usr/bin/env perl6

use lib ".";
use somelib;

my $x = 6;
my $y = 8;

# ouput: (6 8)
dump_value(<$x $y>);

# error: No such symbol 'OUTER::CALLERS::$x'
wrapped_dump_value(<$x $y>);

Ответы [ 2 ]

0 голосов
/ 04 февраля 2019

Согласно документации :

Начальный :: не подразумевает глобальный.Здесь, как часть синтаксиса интерполяции, он даже не подразумевает пакет.После интерполяции компонента: :() косвенное имя ищется точно так же, как если бы оно было в исходном исходном коде, причем приоритет отдается сначала именам псевдопакетов, а затем именам в лексической области (поисквыходит за пределы, заканчиваясь на CORE).

Поэтому, когда вы пишете say ::("$symbol") в dump_value() в пакете somelib, он сначала будет искать $symbol в текущей области, которая имеет значение'$x' затем попробуйте поискать $x (также в текущей области видимости), но переменная $x определена в лексической области видимости вызывающего, поэтому вы получите ошибку No such symbol '$x'.

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

CALLER::MY::($symbol);  # lexical symbols from the immediate caller's lexical scope

или

 CALLERS::($symbol); # Dynamic symbols in any caller's lexical scope

см. страница документации пакета .

0 голосов
/ 04 февраля 2019

Пара вещей:

use lib ".";
use somelib;
our $x = 10;     # You need to export the value into the global scope
dump_value('$x');

Затем используйте глобальную область действия :

unit module somelib;

sub dump_value($symbol) is export {
    say GLOBAL::("$symbol")
}
...