Perl6:将函数加载到其他命名空间

byt*_*nit 7 namespaces module perl6

我想使用Perl6模块对一些函数进行分组,我经常使用.因为这些函数都是松散耦合的,所以我不喜欢在类中添加它们.

我喜欢use你可以选择哪些函数应该被导入但我不喜欢它的想法,导入的函数然后存储在全局命名空间中.

例如,如果我有一个文件my_util.pm6:

#content of my_util.pm6
unit module my_util;
our sub greet($who) is export(:greet) {
    say $who;
}
sub greet2($who) is export(:greet2) {
    say $who;
}
sub greet3($who) is export(:greet3) {
    say $who;
}
Run Code Online (Sandbox Code Playgroud)

和一个文件test.p6:

#!/usr/bin/perl6
#content of test.p6
use v6.c;
use lib '.';
use my_util :greet2;

greet("Bob");    #should not work (because no namespace given) and also doesn't work
greet2("Bob");   #should not work (because no namespace given) but actually works
greet3("Bob");   #should not work (because no namespace given) and also doesn't work
my_util::greet("Alice");     #works, but should not work (because it is not imported)
my_util::greet2("Alice");    #should work, but doesn't work
my_util::greet3("Alice");    #should not work (because it is not imported) and also doesn't work
Run Code Online (Sandbox Code Playgroud)

我想通过my_util::greet()而不是通过greet()仅调用所有功能.

greet()定义的函数my_util.pm6非常接近我的要求,但因为它被定义为我们的,所以它总是被导入.我喜欢的是选择应该导入哪些函数的可能性,并且应该可以将它留在模块定义的命名空间中(即它不会污染全局命名空间)

有谁知道,我怎么能做到这一点?

sml*_*mls 7

澄清一些潜在的混乱......

词法范围和包符号表是不同的东西.

  1. my当前词法范围中添加符号.

  2. our将符号添加到当前词法范围,并添加到当前包的公共符号表.

  3. use将请求的符号复制到当前词法范围.
    那被称为"导入".

  4. ::分离器做了包查找-即foo::greet查找符号greet公共符号表foo.
    这不涉及任何"导入".

至于你想要实现的目标......

无论从何处引用,包的公共符号表都是相同的......没有任何机制可以使不同范围内的单个符号可见.

可以使冒号成为子程序实际名称的一部分......

sub foo::greet($who) is export(:greet) { say "Hello, $who!" }
# This subroutine is now literally called "foo::greet".
Run Code Online (Sandbox Code Playgroud)

...但是你不能再以正常方式调用它了(因为解析器会将其解释为上面的规则4),所以你必须使用笨重的"间接词法查找"语法,这显然不是你的意思想:

foo::greet "Sam";          # Could not find symbol '&greet'
::<&foo::greet>( "Sam" );  # Hello, Sam!
Run Code Online (Sandbox Code Playgroud)

所以,你最好的选择是......

  • 声明与子程序our,并且与事实住所有这些都可以从所有范围内是可以访问use的模块.
    要么:
  • 将公共前缀直接添加到子例程名称,但使用无问题的分隔符(例如破折号),然后正常导入它们:
unit module foo;
sub foo-greet($who)  is export(:greet)  { ... }
sub foo-greet2($who) is export(:greet2) { ... }
sub foo-greet3($who) is export(:greet3) { ... }
Run Code Online (Sandbox Code Playgroud)