在 sub 中通过名称获取符号的值
Get a symbol's value by its name in a sub
我正在制作一个程序包,我必须在子程序中通过符号的名称获取符号的值,而符号是在子程序外部定义的。
这里是简化后的代码,按预期运行:
#! /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
以下是一些实验。 None 个成功。
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>);
两件事:
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")
}
An initial :: doesn't imply global. Here as part of the interpolation
syntax it doesn't even imply package. After the interpolation of the
::() component, the indirect name is looked up exactly as if it had
been there in the original source code, with priority given first to
leading pseudo-package names, then to names in the lexical scope
(searching scopes outwards, ending at CORE).
所以当你在somelib
包中的dump_value()
中写say ::("$symbol")
时,它会先在当前作用域中查找$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
我正在制作一个程序包,我必须在子程序中通过符号的名称获取符号的值,而符号是在子程序外部定义的。
这里是简化后的代码,按预期运行:
#! /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
以下是一些实验。 None 个成功。
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>);
两件事:
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")
}
An initial :: doesn't imply global. Here as part of the interpolation syntax it doesn't even imply package. After the interpolation of the ::() component, the indirect name is looked up exactly as if it had been there in the original source code, with priority given first to leading pseudo-package names, then to names in the lexical scope (searching scopes outwards, ending at CORE).
所以当你在somelib
包中的dump_value()
中写say ::("$symbol")
时,它会先在当前作用域中查找$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