lov*_*ato 6 scope string-interpolation perl6 symbol-table raku
我正在创建一个包,我必须通过它在sub中的名称来获取符号的值,而符号在sub之外定义.
这是简化的代码,它按预期工作:
#! /usr/bin/env perl6
sub dump_value($symbol) {
say ::("$symbol")
}
# usage:
my $x = 10;
dump_value('$x');
# expected output: 10
# actual output: 10
Run Code Online (Sandbox Code Playgroud)
然后我将'dump_value'放在一个独立的文件中,如下所示:
# somelib.pm6
unit module somelib;
sub dump_value($symbol) is export {
say ::("$symbol")
}
Run Code Online (Sandbox Code Playgroud)
# client.pl6
#! /usr/bin/env perl6
use lib ".";
use somelib;
my $x = 10;
dump_value('$x');
Run Code Online (Sandbox Code Playgroud)
编译抱怨:
No such symbol '$x'
in sub dump_value at xxx/somelib.pm6 (somelib) line 3
in block <unit> at ./client.pl6 line 8
Run Code Online (Sandbox Code Playgroud)
以下是一些实验.他们都没有成功.
say ::("MY::$symbol")
say ::("OUR::$symbol")
say ::("OUTER::$symbol")
say ::("CLIENT::$symbol")
...
Run Code Online (Sandbox Code Playgroud)
那么如何修复代码呢?
更新:
谢谢!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) } )
}
Run Code Online (Sandbox Code Playgroud)
# client.pl6
#! /usr/bin/env perl6
use lib ".";
use somelib;
my $x = 6;
my $y = 8;
dump_value(<$x $y>);
Run Code Online (Sandbox Code Playgroud)
再次更新:
用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)
}
Run Code Online (Sandbox Code Playgroud)
#! /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>);
Run Code Online (Sandbox Code Playgroud)
根据文件:
初始::不暗示全局.这里作为插值语法的一部分,它甚至不暗示包.插入:: (()组件后,间接名称的查找方式与原始源代码中的名称完全相同,优先级先于伪包名,然后是词法范围中的名称(搜索范围向外,以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
Run Code Online (Sandbox Code Playgroud)
要么
CALLERS::($symbol); # Dynamic symbols in any caller's lexical scope
Run Code Online (Sandbox Code Playgroud)
请参阅包文档页面.