Perl类属性组成?

发布于 2024-10-15 00:01:43 字数 2239 浏览 8 评论 0原文

假设我有多个角色,每个角色定义一组项目:

package A;
use Moose::Role;
sub items () { qw/apple orange/ }

package B;
use Moose::Role;
with 'A';
sub items () { qw/watermelon/ }

package C;
use Moose::Role;
sub items () { qw/banana/ }

假设我在另一个类中使用它们并且我想收集所有这些项目:

package Foo;
use Moose;
with qw(B C);

sub do_something {
    my $self = shift;
    my @items = ???;   # How can I get apple, orange, watermelon, banana here?
    ....
}

一个可能的解决方案是采用 MooseX::ComposedBehavior 但它的 POD 说(在撰写本文时) ,当然)它的 API“不太稳定”,而且“当前的实现是一种黑客行为,应该被更强大的实现所取代”。因此,我正在研究是否可以在不依赖这种“黑客”的情况下实现这一目标。

警告:如果您以后阅读本文,请查看MooseX::ComlatedBehavior (当前版本:0.003),因为它可能同时发生了变化。事情变化很快。 CPAN 作者发布了新版本。目前“不太稳定”的东西将来可能会变得更加稳定。甚至可能还有其他模块。检查一下你自己。

理想情况下应该是这样的: my @items = map $_->items, @ISA; 然而这对 Moose 不起作用。有没有更好、更可靠的解决方案?


更新:我最终得到了这个三行解决方案:

package A;
use Moose::Role;
sub items () { qw/apple orange/ }

package B;
use Moose::Role;
with 'A';
sub items () { qw/watermelon/ }

package C;
use Moose::Role;
sub items () { qw/banana/ }

package Foo;
use Moose;
with qw(B C);
sub items () {}

sub do_something {
    my $self = shift;

    my @items = map $_->execute, grep $_, 
        map $_->get_method('items'),
        $self->meta->calculate_all_roles_with_inheritance;

    ...
}

更新:正如许多人在#moose IRC 频道 我删除了之前关于 MooseX::ComposedBehavior “不稳定”的断言,并将其替换为从其 POD 中获取的文字文本。


更新:我编写了一个 MooseX::Collect 模块它允许使用以下语法:

package Foo;
use Moose;
use MooseX::Collect;

collect 'items';
with qw(B C);

sub do_something {
    my $self = shift;
    my @items = $self->items;
    ...
}

Suppose I have multiple roles, each one defining a set of items:

package A;
use Moose::Role;
sub items () { qw/apple orange/ }

package B;
use Moose::Role;
with 'A';
sub items () { qw/watermelon/ }

package C;
use Moose::Role;
sub items () { qw/banana/ }

Suppose I use them in another class and I want to collect all those items:

package Foo;
use Moose;
with qw(B C);

sub do_something {
    my $self = shift;
    my @items = ???;   # How can I get apple, orange, watermelon, banana here?
    ....
}

One possible solution is to adopt MooseX::ComposedBehavior but its POD says (at the time of writing, of course) that its API "is not quite stable" and also that "the current implementation is something of a hack, and should be replaced by a more robust one". Thus I'm investigating whether this could be accomplished without relying on such a "hack".

Warning: if you are reading this in the future, please go to check the POD of MooseX::ComposedBehavior (current version: 0.003) because it might have changed in the mean time. Things change quickly. CPAN authors release new versions. What's "not quite stable" at the moment might become more stable in the future. There might even be other modules. Check yourself.

Ideally there should be something like: my @items = map $_->items, @ISA;
However that won't work with Moose. Are there any nicer and more reliable solutions?


Update: I ended up with this three-line solution:

package A;
use Moose::Role;
sub items () { qw/apple orange/ }

package B;
use Moose::Role;
with 'A';
sub items () { qw/watermelon/ }

package C;
use Moose::Role;
sub items () { qw/banana/ }

package Foo;
use Moose;
with qw(B C);
sub items () {}

sub do_something {
    my $self = shift;

    my @items = map $_->execute, grep $_, 
        map $_->get_method('items'),
        $self->meta->calculate_all_roles_with_inheritance;

    ...
}

Update: As various people requested me in the #moose IRC channel I removed my previous assertion that MooseX::ComposedBehavior "is not stable" and replaced it with literal text taken from its POD.


Update: I wrote a MooseX::Collect module which allows the following syntax:

package Foo;
use Moose;
use MooseX::Collect;

collect 'items';
with qw(B C);

sub do_something {
    my $self = shift;
    my @items = $self->items;
    ...
}

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

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

发布评论

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

评论(2

蘑菇王子 2024-10-22 00:01:43

需要使用around

package A;
use Moose::Role;
requires 'items';
around items => sub {
    my ($orig, $self, @args) = @_;
    return ($self->$orig(@args), qw/apple orange/);
};

package B;
use Moose::Role;
requires 'items';
with 'A'; # not required, do it if you want it
around items => sub {
    my ($orig, $self, @args) = @_;
    return ($self->$orig(@args), qw/watermelon/);
};

package C;
use Moose::Role;
requires 'items';
around items => sub {
    my ($orig, $self, @args) = @_;
    return ($self->$orig(@args), qw/banana/);
};

package Class;
use Moose;
with qw/B C/;
sub items {}

但是一般来说,用类来表示数据是错误的,就是这样
类的实例是为了。由于您的示例非常简单,因此很难提供进一步的建议。你到底想做什么?

You need to use around:

package A;
use Moose::Role;
requires 'items';
around items => sub {
    my ($orig, $self, @args) = @_;
    return ($self->$orig(@args), qw/apple orange/);
};

package B;
use Moose::Role;
requires 'items';
with 'A'; # not required, do it if you want it
around items => sub {
    my ($orig, $self, @args) = @_;
    return ($self->$orig(@args), qw/watermelon/);
};

package C;
use Moose::Role;
requires 'items';
around items => sub {
    my ($orig, $self, @args) = @_;
    return ($self->$orig(@args), qw/banana/);
};

package Class;
use Moose;
with qw/B C/;
sub items {}

But in general, using classes to represent data is wrong, that's what
instances of classes are for. It's hard to provide further advice since your example is so trival. What are you really trying to do?

看透却不说透 2024-10-22 00:01:43

在您指向 MooseX::ComposedBehavior 之前在 IRC 上,我不完全确定为什么您认为不应该使用它。毕竟,它确实可以解决您遇到的问题。

是的,它确实说它的界面将来可能会略有变化。然而,要适应这些细微的变化,你需要付出多少努力呢?相比之下,您认为需要多长时间才能提出替代解决方案并实际实施?您认为您的解决方案在正确性和鲁棒性等方面与 MooseX::ComposedBehavior 相比如何?至少我不会相信自己会重新发明 RJBS 最初发明的轮子并期望我的解决方案会变得更好。

另外,如果你真的非常担心某个模块会警告你未来可能发生的变化,请与它的作者合作,帮助他将其调整为他满意的状态,并宣布其稳定。为您的特定用例编写更多测试。和里卡多谈谈,他是个好人。

After having you pointed at MooseX::ComposedBehavior before on IRC, I'm not entirely sure why you feel you shouldn't be using it. It does, after all, solve exactly the problem you're having.

Yes, it does say its interface may change slightly in the future. However, how much work will it be for you to adapt to those slight changes? In comparison, how long do you think it'll take you to come up with an alternative solution and to actually implement that? How do you think will your solution compare to MooseX::ComposedBehavior in things like correctness and robustness? At least I wouldn't trust myself in reinventing a wheel originally invented by RJBS and expecting my solution to turn out better.

Also, if you're really super worried about a module warning you about possible future changes, go work with its author and help him get it into a shape that he's happy with for declaring it as stable. Write some more tests for your specific usecase. Talk to Ricardo, he's a nice guy.

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