Beefy Boxes and Bandwidth Generously Provided by pair Networks
Perl-Sensitive Sunglasses
 
PerlMonks  

Re: OO Pattern Container x Elements and Method Chaining

by choroba (Cardinal)
on Oct 08, 2021 at 15:38 UTC ( [id://11137354]=note: print w/replies, xml ) Need Help??


in reply to OO Pattern Container x Elements and Method Chaining

Something like this?
#!/usr/bin/perl use warnings; use strict; use feature qw{ say }; { package Element; use Moo; has name => (is => 'ro'); has active_container => (is => 'rw'); } { package Container; use Moo; has elements => (is => 'ro', default => sub { [] }); sub add_elem { my ($self, $element) = @_; push @{ $self->elements }, $element unless grep $_ == $element, @{ $self->elements }; } sub get_elem { my ($self, $name) = @_; my $elem = (grep $_->name eq $name, @{ $self->elements })[0]; $elem->active_container($self); return $elem } } my $elem1 = 'Element'->new(name => 'one'); my ($cont1, $cont2) = map 'Container'->new, 1, 2; $cont1->add_elem($elem1); $cont2->add_elem($elem1); $cont1 == $cont1->get_elem('one')->active_container and say 'ok'; $cont2 == $cont2->get_elem('one')->active_container and say 'ok';

You should probably make some of the slots weak.

Update: Oh, I know see what the problem is. It works for chained methods *exclusively*, i.e. it doesn't work for non-chained methods.

my $e1 = $cont1->get_elem('one'); my $e2 = $cont2->get_elem('one'); $e1->active_container ne $e2->active_container or die;

For that, you need a wrapper. Maybe it's possible to overload it so it returns the wrapped element's ref when compared numerically, so $e1 == $e2 still holds?

map{substr$_->[0],$_->[1]||0,1}[\*||{},3],[[]],[ref qr-1,-,-1],[{}],[sub{}^*ARGV,3]

Replies are listed 'Best First'.
Re^2: OO Pattern Container x Elements and Method Chaining
by LanX (Saint) on Oct 08, 2021 at 15:48 UTC
    Thanks a lot

    > You should probably make some of the slots weak.

    of course, but ...

    I hope this makes it clearer now:

    #!/usr/bin/perl use warnings; use strict; use feature qw{ say }; { package Element; use Moo; has name => (is => 'ro'); has active_container => (is => 'rw'); } { package Container; use Moo; has elements => (is => 'ro', default => sub { [] }); sub add_elem { my ($self, $element) = @_; push @{ $self->elements }, $element unless grep $_ == $element, @{ $self->elements }; } sub get_elem { my ($self, $name) = @_; my $elem = (grep $_->name eq $name, @{ $self->elements })[0]; $elem->active_container($self); return $elem } } my $elem0 = 'Element'->new(name => 'one'); my ($cont1, $cont2) = map 'Container'->new, 1, 2; $cont1->add_elem($elem0); $cont2->add_elem($elem0); my $elem1 = $cont1->get_elem('one'); say "OK" if $elem1->active_container == $cont1; my $elem2 = $cont2->get_elem('one'); say "OK" if $elem2->active_container == $cont2; print "Not OK" if $elem1->active_container != $cont1;

    C:/Strawberry/perl/bin\perl.exe -w d:/tmp/pm/container_elem.pl OK OK Not OK Compilation finished at Fri Oct 8 17:48:07

    Cheers Rolf
    (addicted to the Perl Programming Language :)
    Wikisyntax for the Monastery

      Yes, a wrapper with overloaded numeric comparison seems to work:
      #!/usr/bin/perl use warnings; use strict; use feature qw{ say }; { package Element; use Moo; has name => (is => 'ro'); } { package Element::Wrapped; use Moo; use overload '==' => sub { $_[0]->element == $_[1]->element }, fallback => 1; has element => (is => 'ro', required => 1, handles => [qw[ name ]]); # <- and any other Elem +ent methods. has active_container => (is => 'rw'); } { package Container; use Moo; has elements => (is => 'ro', default => sub { [] }); sub add_elem { my ($self, $element) = @_; push @{ $self->elements }, $element unless grep $_ == $element, @{ $self->elements }; } sub get_elem { my ($self, $name) = @_; my $elem = (grep $_->name eq $name, @{ $self->elements })[0]; my $wrap = 'Element::Wrapped'->new(element => $elem); $wrap->active_container($self); return $wrap } } use Test2::V0; plan 6; my $elem1 = 'Element'->new(name => 'one'); my ($cont1, $cont2) = map 'Container'->new, 1, 2; $cont1->add_elem($elem1); $cont2->add_elem($elem1); is $cont1->get_elem('one')->active_container, $cont1; is $cont2->get_elem('one')->active_container, $cont2; my $e1 = $cont1->get_elem('one'); my $e2 = $cont2->get_elem('one'); ok $e1->active_container != $e2->active_container; ok $e1 == $e2; is $e1->name, 'one'; is $e1->name, $e2->name;
      map{substr$_->[0],$_->[1]||0,1}[\*||{},3],[[]],[ref qr-1,-,-1],[{}],[sub{}^*ARGV,3]
        Thanks a lot, again.

        my Moo(se)->skills are still limited

        I don't think the overload is really necessary, I don't mind if two Wrapper::Elements identify differently

        handles intrigues me, do you know how it's implemented?

        Unfortunately we have a performance issue, too.

        and

        > # <- and any other Element methods.

        means the delegated methods must be listed explicitly and updated when Element grows in methods? °

        That's why I mentioned AUTOLOAD and/or inheritance in the OP.

        Cheers Rolf
        (addicted to the Perl Programming Language :)
        Wikisyntax for the Monastery

        UPDATE

        according to https://metacpan.org/pod/Moose#REGEXP I can dynamically filter all methods needed to be delegated at compiletime :)

Log In?
Username:
Password:

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: note [id://11137354]
help
Chatterbox?
and the web crawler heard nothing...

How do I use this?Last hourOther CB clients
Other Users?
Others about the Monastery: (3)
As of 2024-04-19 20:21 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found