我正在编写一个包含一些部分的绘图包,我有分散的运算符和数据类型。然而,我不希望用户每次都添加相应的模块,因为它会很混乱,例如,我会在不同的路径中有一个Point
类、一个Monod
角色和一个Style
类
unit module Package::Data::Monoid;
# $?FILE = lib/Package/Data/Monoid.pm6
role Monoid {...}
unit module Package::Data::Point;
# $?FILE = lib/Package/Data/Point.pm6
class Point {...}
unit module Package::Data::Style;
# $?FILE = lib/Package/Data/Style.pm6
class Style {...}
我想在lib/Package/Prelude. pm6
中有一个类似haskell
的前奏,效果是我可以编写这样的脚本
use Package::Prelude;
# I can use Point right away, Style etc...
而不是做
use Package::Data::Style;
use Package::Data::Point;
use Package::Data::Monoid;
# I can too use point right away, but for users not knowing the
# inner workings it's too overwhelming
我尝试过很多东西:
Package::Data::Point
…unit module Package::Prelude;
# $?FILE = lib/Package/Prelude.pm6
use Package::Data::Style;
use Package::Data::Point;
use Package::Data::Monoid;
Point
,但是我遇到了运算符等问题,我也想自动添加上述示例包中导出例程中的所有内容。# $?FILE = lib/Package/Prelude.pm6
use Package::Data::Style;
use Package::Data::Point;
use Package::Data::Monoid;
sub EXPORT {
hash <Point> => Point
, <Style> => Style
, <mappend> => &mappend
...
}
你们这些人知道更好更快的方法来获得这样一个前奏般的文件吗?
使用EXPORT
是正确的方向。要知道的关键是:
所以食谱是:
使用
EXPORTEXPORT
例如,我创建了一个模块Foo::Point
,包括一个运算符和一个类:
unit module Foo::Point;
class Point is export {
has ($.x, $.y);
}
multi infix:<+>(Point $a, Point $b) is export {
Point.new(x => $a.x + $b.x, y => $a.y + $b.y)
}
而且,为了证明它可以与多个模块一起使用,还有一个Foo::Monad
:
unit module Foo::Monad;
class Monad is export {
method explain() { say "Just think of a burrito..." }
}
目标是使这项工作:
use Foo::Prelude;
say Point.new(x => 2, y => 4) + Point.new(x => 3, y => 5);
Monad.explain;
这可以通过编写包含以下内容的Foo::Prelud
来实现:
sub EXPORT() {
{
use Foo::Point;
use Foo::Monad;
return ::.pairs.grep(*.key ne '$_').Map;
}
}
这里有一些奇怪的事情要解释:
sub
具有$_
、$/
和$!
的隐式声明。当模块use
'd时,导出这些将导致编译时符号冲突错误。一个块只有一个隐式的$_
。因此,我们使用嵌套的裸块使我们的生活更轻松。grep
是为了确保我们不会导出隐式声明的$_
符号(多亏了嵌套块,它是我们唯一需要关心的)。::
是引用当前作用域的一种方式(词源:::
是包分隔符)。::对
从而获得当前作用域中每个符号的对
对象。有一种推测的再导出机制可能会出现在未来的Raku语言版本中,这将消除对这一点样板的需求。