在Moose子例程中,$meta如何进入@_?
Chromatic 最近的博客让我很好奇关于 Moose 子例程has
。我正在查看 Moose 源代码,注意到在 has
子例程中,有一个从 @_
解压出来的 $meta
变量。 $meta
从哪里来?我已经开始涉足各种 Moose 和 Class::MOP 模块。在许多子例程中,$meta
似乎通常作为 @_
中的第一个参数出现,即使它没有专门作为参数传递给它。
编辑:这是 has
子例程的原始源代码:
sub has {
my $meta = shift;
my $name = shift;
Moose->throw_error('Usage: has \'name\' => ( key => value, ... )')
if @_ % 2 == 1;
my %options = ( definition_context => Moose::Util::_caller_info(), @_ );
my $attrs = ( ref($name) eq 'ARRAY' ) ? $name : [ ($name) ];
$meta->add_attribute( $_, %options ) for @$attrs;
}
chromatic's recent blog got me curious about the Moose subroutine has
. I was looking at the Moose source code and noticed that inside the has
subroutine, there is a $meta
variable unpacked from @_
. Where does $meta
come from? I've started wading through the various Moose and Class::MOP modules. In many subroutines, it seems that $meta
is commonly found as the first argument in @_
, even though it is not specifically passed to it as an argument.
Edit: Here is the original source code for the has
subroutine:
sub has {
my $meta = shift;
my $name = shift;
Moose->throw_error('Usage: has \'name\' => ( key => value, ... )')
if @_ % 2 == 1;
my %options = ( definition_context => Moose::Util::_caller_info(), @_ );
my $attrs = ( ref($name) eq 'ARRAY' ) ? $name : [ ($name) ];
$meta->add_attribute( $_, %options ) for @$attrs;
}
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
您正在寻找的特殊魔力就在 Moose::Exporter 中。您可以通过 Moose.pm 从此代码中获取
has
方法:请注意
setup_import_methods
的“with_meta”选项 - 它将这些方法导入到调用者的命名空间中,以确保传递的第一个参数将是元类对象。扩展 Moose 的各种 MooseX 模块使用 Moose::Exporter 将新符号导入到调用者的命名空间中。您可以在食谱中阅读有关此过程的更多信息,从 Moose 开始: :Cookbook::Extending::Recipe1。
The particular magic you are looking for is in Moose::Exporter. You get the
has
method via Moose.pm from this code:Note the "with_meta" option for
setup_import_methods
-- it imports those methods into the caller's namespace in a manner which ensures that the first argument passed will be the metaclass object.The various MooseX modules that extend Moose use Moose::Exporter to import new symbols into the caller's namespace. You can read more about this process in the cookbook, starting at Moose::Cookbook::Extending::Recipe1.
实际上导入到包中的不是命名的 has() 子例程,而是插入元对象的闭包。您可以通过以下方式准确了解这是如何发生的:
$CODE1
是闭包本身;上面是其中引用的变量。What's actually imported into into your package isn't the named has() subroutine but a closure that inserts the meta object. You can see exactly how this happens with:
$CODE1
is the closure itself; above are the variables referenced in it.ysth 答案中的
分子
评论:(希望如此!)一个简单的示例,说明如何实现这一点(但是我怀疑
Moose
以更复杂、更好的方式做到这一点!)Meta.pm
Import.pm
meta_has.pl
现在,如果您运行
meta_has.pl
您将得到:希望有帮助。
/I3az/
molecules
comment in ysth answer:Here is (hopefully!) a simple example of how this could be achieved (however I suspect
Moose
does it in a much more complex and better way!)Meta.pm
Import.pm
meta_has.pl
Now if you run
meta_has.pl
you will get:Hope that helps.
/I3az/