7

这似乎是一个明显没有希望的情况,但是在 Perl 中创建不可变对象的循环图有什么技巧吗?像这样的东西:

package Node;
use Moose;
has [qw/parent child/] => (is => 'ro', isa => 'Node');

package main;
my $a = Node->new;
my $b = Node->new(parent => $a);

现在,如果我想$a->child指向$b,我该怎么办?

4

3 回答 3

5
于 2009-11-21T16:32:53.933 回答
4

我不得不去看看真正不可变的语言是如何做这样的事情的,我认为以下可能是一个合理的尝试。

use 5.10.0;
{

    package Node;
    use Moose;
    has [qw(parent child)] => ( isa => 'Node', is => 'ro' );

    sub BUILD {
        my ( $self, $p ) = @_;
        return unless exists $p->{_child};
        my $child = Node->new( parent => $self, %{ delete $p->{_child} }, );
        $self->meta->get_attribute('child')->set_value( $self, $child );
    }
}

say Node->new( _child => {} )->dump

基本上,不是尝试单独构建对象,而是让父级根据传入的参数自动激活子级。输出是,我相信你想要的结构。

$VAR1 = bless( {
                 'child' => bless( {
                                     'parent' => $VAR1
                                   }, 'Node' )
               }, 'Node' );
于 2009-11-21T18:54:11.717 回答
1

我对 Moose 还是很陌生,但是触发器会起作用吗?

use Modern::Perl;

package Node;
use Moose;
has 'parent' => (
    is => 'ro',
    isa => 'Node',
    trigger => sub{
        my ($self, $parent) = @_;
        $parent->{child} = $self unless defined $parent->child;
    }
);

has 'child' => (
    is => 'ro',
    isa => 'Node',
    trigger => sub{
        my ($self, $child) = @_;
        $child->{parent} = $self unless defined $child->parent;
    }
);

package main;
my $p = Node->new;
my $c = Node->new(parent => $p);

say $p, ' == ', $c->parent;
say $c, ' == ', $p->child;
于 2009-11-21T16:06:18.590 回答