通过子名称获取符号的值

时间:2019-02-04 16:15:24

标签: scope perl6 string-interpolation symbol-table

我正在制作一个包装,其中必须在子对象中通过符号名称获取符号的值,而符号是在子对象外部定义的。

这是简化的代码,可以正常使用:

#! /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>);

3 个答案:

答案 0 :(得分:6)

根据the documentation

  

首字母::并不表示是全局的。这是插值的一部分   甚至不暗示打包的语法。插值后   ::()组件,查找间接名称的方式就好像它具有   在原始源代码中出现过,优先级最高的是   前导伪包名称,然后到词法范围内的名称   (向外搜索范围,以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

请参见the package documentation page

答案 1 :(得分:3)

dump_value('CALLER::MY::$x'); # works with your lib as it is

其他答案解释了发生了什么。

答案 2 :(得分:0)

事物的结合:

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

然后,使用global scope

unit module somelib;

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