使用模块加载一组相关的函数
Using modules to load a group of related functions
我想用Raku Modules来对一些我经常用到的功能进行分组。因为这些功能都是松散耦合的,所以我不喜欢把它们加在一个class.
我喜欢 use
的想法,您可以在其中 select 导入哪些函数,但我不喜欢,导入的函数然后存储在全局命名空间。
例如,如果我有一个文件 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;
}
和一个文件 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
我想通过 my_util::greet()
而不是仅通过 greet()
调用所有函数。
my_util.pm6
中定义的函数greet()
和我的要求很接近,但是因为定义为our,所以总是引入。我喜欢的是 select 应该导入哪些函数的可能性,并且应该可以将它留在模块定义的命名空间中(即它不会污染全局命名空间)
有谁知道,我怎样才能做到这一点?
消除一些潜在的困惑...
词法范围和包符号 table 是不同的东西。
my
添加符号到 当前词法作用域 .
our
将符号添加到 当前词法范围 , 和 到 public 当前包的符号table。
use
将请求的符号复制到 当前词法范围 .
那叫"importing".
::
分隔符执行包查找——即 foo::greet
在 public 符号中查找符号 greet
table 包 foo
。
这不涉及任何"importing".
至于你想达到什么...
包的 public 符号 table 无论从何处引用都是相同的...没有机制可以使其中的各个符号在不同范围内可见。
您可以使冒号成为子程序实际名称的一部分...
sub foo::greet($who) is export(:greet) { say "Hello, $who!" }
# This subroutine is now literally called "foo::greet".
...但是你不能再以正常方式调用它(因为解析器会将其解释为上面的规则 4),所以你将不得不使用笨拙的 "indirect lexical lookup" 语法,它显然不是你想要的:
foo::greet "Sam"; # Could not find symbol '&greet'
::<&foo::greet>( "Sam" ); # Hello, Sam!
所以,您最好的选择是...
- 使用
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) { ... }
我想用Raku Modules来对一些我经常用到的功能进行分组。因为这些功能都是松散耦合的,所以我不喜欢把它们加在一个class.
我喜欢 use
的想法,您可以在其中 select 导入哪些函数,但我不喜欢,导入的函数然后存储在全局命名空间。
例如,如果我有一个文件 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;
}
和一个文件 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
我想通过 my_util::greet()
而不是仅通过 greet()
调用所有函数。
my_util.pm6
中定义的函数greet()
和我的要求很接近,但是因为定义为our,所以总是引入。我喜欢的是 select 应该导入哪些函数的可能性,并且应该可以将它留在模块定义的命名空间中(即它不会污染全局命名空间)
有谁知道,我怎样才能做到这一点?
消除一些潜在的困惑...
词法范围和包符号 table 是不同的东西。
my
添加符号到 当前词法作用域 .our
将符号添加到 当前词法范围 , 和 到 public 当前包的符号table。use
将请求的符号复制到 当前词法范围 .
那叫"importing".::
分隔符执行包查找——即foo::greet
在 public 符号中查找符号greet
table 包foo
。
这不涉及任何"importing".
至于你想达到什么...
包的 public 符号 table 无论从何处引用都是相同的...没有机制可以使其中的各个符号在不同范围内可见。
您可以使冒号成为子程序实际名称的一部分...
sub foo::greet($who) is export(:greet) { say "Hello, $who!" }
# This subroutine is now literally called "foo::greet".
...但是你不能再以正常方式调用它(因为解析器会将其解释为上面的规则 4),所以你将不得不使用笨拙的 "indirect lexical lookup" 语法,它显然不是你想要的:
foo::greet "Sam"; # Could not find symbol '&greet'
::<&foo::greet>( "Sam" ); # Hello, Sam!
所以,您最好的选择是...
- 使用
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) { ... }