将 MX::Declare 方法定义为属性触发器

发布于 2024-12-15 05:41:43 字数 3587 浏览 0 评论 0原文

以下代码按我的预期工作。当它所依赖的 foo 属性发生更改时,缓存的惰性属性将被清除并重建。

use MooseX::Declare;
use 5.010;

class Test {
  has foo => ( isa => 'Str', is => 'rw', trigger => sub {my $self = shift; $self->clearer}, default => '' );

  has lazy => ( isa => 'Str', is => 'ro', lazy => 1, clearer => 'clearer',
                default => method { say 'building lazy'; return "foo is '".$self->foo."'"; },
              );

  method say ( ) {
    say $self->lazy;
  }
}

my $inst = Test->new( foo => 'baz' );
$inst->say;
$inst->say;
say $inst->foo();
$inst->foo('bar'); 
$inst->say;

输出:

building lazy
foo is 'baz'
foo is 'baz'
baz
building lazy
foo is 'bar'

但是,我如何使用 MX::Declare 糖来触发子例程?将 foo 定义为:

has foo => ( isa => 'Str', is => 'rw', trigger => method {$self->clearer}, default => '' );

导致类在编译时死亡(如下)。我的匿名方法声明有问题吗?

触发器必须是属性 (foo) 的代码引用,位于 C:/Strawberry/perl/site/lib/Moose/Meta/Attribute.pm 第 423 行 Moose::Meta::Attribute::_process_trigger_option('Moose::Meta::Attribute', 'foo', 'HASH(0x2a5d14c)') 在 C: 调用 /Strawberry/perl/site/lib/Moose/Meta/Attribute.pm 第 299 行 Moose::Meta::Attribute::_process_options('Moose::Meta::Attribute', 'foo', 'HASH(0x2a5d14c)') 在 C:/Strawb 调用 erry/perl/site/lib/Moose/Meta/Attribute.pm 第 88 行 Moose::Meta::Attribute::new('Moose::Meta::Attribute', 'foo', 'trigger', 'MooseX::Method::Signatures::Meta::Metho d=HASH(0x39a421c)', 'isa', 'Str', 'definition_context', 在 C:/Straw 调用 'HASH(0x3452184)'、'default'、''、'is'、'rw') berry/perl/site/lib/Moose/Meta/Attribute.pm 第 114 行 Moose::Meta::Attribute::interpolate_class_and_new('Moose::Meta::Attribute', 'foo', 'trigger', 'MooseX::Method::S 签名::Meta::Method=HASH(0x39a421c)', 'isa', 'Str', '默认', '', 'definition_context'、'HASH(0x3452184)'、'is'、'r w') 调用于 C:/Strawberry/perl/site/lib/Moose/Meta/Class.pm 第 704 行 Moose::Meta::Class::_process_new_attribute('Moose::Meta::Class=HASH(0x38c79d4)', 'foo', 'trigger', 'MooseX::Meth od::Signatures::Meta::Method=HASH(0x39a421c)', 'isa', 'Str', '默认'、''、'definition_context'、'HASH(0x3452184)'、'是'、'rw') 调用于 C:/Strawberry/perl/site/lib/Moose/Meta/Class.pm 第 697 行 Moose::Meta::Class::_process_attribute('Moose::Meta::Class=HASH(0x38c79d4)', 'foo', 'trigger', 'MooseX::方法:: 签名::Meta::Method=HASH(0x39a421c)', 'isa', 'Str', '默认', ''、'definition_context'、'HASH(0x3452184)'、'is'、'rw') 调用于 C:/Strawberry/perl/site/lib/Moose/Meta/Class.pm 第 566 行 Moose::Meta::Class::add_attribute('Moose::Meta::Class=HASH(0x38c79d4)', 'foo', 'trigger', 'MooseX::Method::Signa tures::Meta::Method=HASH(0x39a421c)', 'isa', 'Str', '默认', '', 'definition_context'、'HASH(0x3452184)'、'is'、'rw') 调用于 C:/Strawberry/perl/site/lib/Moose.pm 第 77 行 Moose::has('Moose::Meta::Class=HASH(0x38c79d4)', 'foo', 'isa', 'Str', 'is', 'rw', 'trigger', 'MooseX::Method: :硅 gnatures::Meta::Method=HASH(0x39a421c)', 'default', '') 调用于 C:/Strawberry/perl/site/lib/Moose/Exporter.pm 第 356 行

 Moose::has('foo', 'isa', 'Str', 'is', 'rw', 'trigger', 'MooseX::Method::Signatures::Meta::Method=哈希(0x39a421c) ',

'default', '') 在 mx_declare.pl 第 5 行调用 main::ANON() 在 C:/Strawberry/perl/site/lib/MooseX/Declare/Syntax/MooseSetup.pm 行调用 81 MooseX::声明::语法::MooseSetup::匿名('代码(0x38c3a94)') 在 mx_declare.pl 第 13 行调用

The following code works as I'd expect. The cached lazy attribute gets cleared and rebuilt when the foo attribute it depends on is changed.

use MooseX::Declare;
use 5.010;

class Test {
  has foo => ( isa => 'Str', is => 'rw', trigger => sub {my $self = shift; $self->clearer}, default => '' );

  has lazy => ( isa => 'Str', is => 'ro', lazy => 1, clearer => 'clearer',
                default => method { say 'building lazy'; return "foo is '".$self->foo."'"; },
              );

  method say ( ) {
    say $self->lazy;
  }
}

my $inst = Test->new( foo => 'baz' );
$inst->say;
$inst->say;
say $inst->foo();
$inst->foo('bar'); 
$inst->say;

output:

building lazy
foo is 'baz'
foo is 'baz'
baz
building lazy
foo is 'bar'

How do I, however, use the MX::Declare sugar for the trigger subroutine? Defining foo as:

has foo => ( isa => 'Str', is => 'rw', trigger => method {$self->clearer}, default => '' );

Results in the class dying on compilation (below). Am I doing something wrong with my anonymous method declaration?

Trigger must be a CODE ref on attribute (foo) at
C:/Strawberry/perl/site/lib/Moose/Meta/Attribute.pm line 423
Moose::Meta::Attribute::_process_trigger_option('Moose::Meta::Attribute',
'foo', 'HASH(0x2a5d14c)') called at C:
/Strawberry/perl/site/lib/Moose/Meta/Attribute.pm line 299
Moose::Meta::Attribute::_process_options('Moose::Meta::Attribute',
'foo', 'HASH(0x2a5d14c)') called at C:/Strawb
erry/perl/site/lib/Moose/Meta/Attribute.pm line 88
Moose::Meta::Attribute::new('Moose::Meta::Attribute', 'foo', 'trigger', 'MooseX::Method::Signatures::Meta::Metho
d=HASH(0x39a421c)', 'isa', 'Str', 'definition_context',
'HASH(0x3452184)', 'default', '', 'is', 'rw') called at C:/Straw
berry/perl/site/lib/Moose/Meta/Attribute.pm line 114
Moose::Meta::Attribute::interpolate_class_and_new('Moose::Meta::Attribute',
'foo', 'trigger', 'MooseX::Method::S
ignatures::Meta::Method=HASH(0x39a421c)', 'isa', 'Str', 'default', '',
'definition_context', 'HASH(0x3452184)', 'is', 'r w') called at
C:/Strawberry/perl/site/lib/Moose/Meta/Class.pm line 704
Moose::Meta::Class::_process_new_attribute('Moose::Meta::Class=HASH(0x38c79d4)',
'foo', 'trigger', 'MooseX::Meth
od::Signatures::Meta::Method=HASH(0x39a421c)', 'isa', 'Str',
'default', '', 'definition_context', 'HASH(0x3452184)', 'is ', 'rw')
called at C:/Strawberry/perl/site/lib/Moose/Meta/Class.pm line 697
Moose::Meta::Class::_process_attribute('Moose::Meta::Class=HASH(0x38c79d4)',
'foo', 'trigger', 'MooseX::Method::
Signatures::Meta::Method=HASH(0x39a421c)', 'isa', 'Str', 'default',
'', 'definition_context', 'HASH(0x3452184)', 'is', ' rw') called at
C:/Strawberry/perl/site/lib/Moose/Meta/Class.pm line 566
Moose::Meta::Class::add_attribute('Moose::Meta::Class=HASH(0x38c79d4)',
'foo', 'trigger', 'MooseX::Method::Signa
tures::Meta::Method=HASH(0x39a421c)', 'isa', 'Str', 'default', '',
'definition_context', 'HASH(0x3452184)', 'is', 'rw') called at
C:/Strawberry/perl/site/lib/Moose.pm line 77
Moose::has('Moose::Meta::Class=HASH(0x38c79d4)', 'foo', 'isa', 'Str', 'is', 'rw', 'trigger', 'MooseX::Method::Si
gnatures::Meta::Method=HASH(0x39a421c)', 'default', '') called at
C:/Strawberry/perl/site/lib/Moose/Exporter.pm line 356

    Moose::has('foo', 'isa', 'Str', 'is', 'rw', 'trigger', 'MooseX::Method::Signatures::Meta::Method=HASH(0x39a421c) ',

'default', '') called at mx_declare.pl line 5
main::ANON() called at C:/Strawberry/perl/site/lib/MooseX/Declare/Syntax/MooseSetup.pm line
81
MooseX::Declare::Syntax::MooseSetup::ANON('CODE(0x38c3a94)')
called at mx_declare.pl line 13

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

香草可樂 2024-12-22 05:41:43

method 关键字返回 MooseX::Method::Signatures::Meta::Method 类的实例,该类是 Moose::Meta: 的子类: :Method,它是Class::MOP::Method的子类。

Moose 允许使用 default 的方法对象,但不允许使用 trigger 的方法对象,后者必须是常规的 coderef。

如果您确实想在那里使用 method 关键字,您可能会这样做:

trigger => method { $self->clearer }->body,

但是按照 @cjm 的建议进行操作并仅使用常规的 coderef 可能会更容易(并且更明智):

trigger => sub { shift->clearer },

The method keyword returns an instance of the MooseX::Method::Signatures::Meta::Method class, which is a subclass of Moose::Meta::Method, which is a subclass of Class::MOP::Method.

Moose allows a method object for default, but not for trigger, which must be a regular coderef.

If you really want to use the method keyword there, you could probably do:

trigger => method { $self->clearer }->body,

But it's probably easier (and saner) to do what @cjm suggests and just use a regular coderef:

trigger => sub { shift->clearer },
淡淡の花香 2024-12-22 05:41:43

你不能。 method 返回一个对象,而不是普通的 coderef。但是,您可以比 method 允许的方式编写得更简洁:

has foo => ( isa => 'Str', is => 'rw', trigger => sub {shift->clearer}, default => '' );

这比 method {$self->clearer} 短 3 个字符。而且它的开销更少。

You can't. method returns an object, not a plain coderef. However, you can write this even more concisely than method would allow:

has foo => ( isa => 'Str', is => 'rw', trigger => sub {shift->clearer}, default => '' );

That's 3 characters shorter than method {$self->clearer}. And it has less overhead.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文