Beefy Boxes and Bandwidth Generously Provided by pair Networks
"be consistent"
 
PerlMonks  

UNIVERSAL->cando , shortcut for testing and running methods?

by Boldra (Deacon)
on Mar 06, 2009 at 07:11 UTC ( [id://748756]=perlquestion: print w/replies, xml ) Need Help??

Boldra has asked for the wisdom of the Perl Monks concerning the following question:

I love the // operator in perl5.10.

Now
my $home = defined( $args->{home} ) ? $args->{home} : defined($args->{house}) ? $args->{house} : confess(q{Can't determine home});
can be simplified to
my $home = $args->{home} // $args->{house} // confess(q{Can't determin +e home});


But if I'm using a super class, is there a shortcut for:
my $home = $self->can('home') ? $self->home : $self->can('house') ? $self->house(1) : confess(q{Can't determine home});
Something that would let me write it something like this:
my $home = $self->cando('home') // $self->cando('house',1) // confess( +q{Can't determine home});
?


- Boldra

Replies are listed 'Best First'.
Re: UNIVERSAL->cando , shortcut for testing and running methods?
by ikegami (Patriarch) on Mar 06, 2009 at 07:15 UTC

    No need to make up new operatorsadd a method to every single class when a sub will do just fine.

    sub cando { my $o = shift; my $m = shift; return if !eval { $o->can($m) }; return $o->$m(@_); } my $home = cando($self, 'home') // cando($self, 'house', 1) // confess(q{Can't determine home});

    Keep in mind neither your operatormethod nor this sub will work right if home returns undef.

Re: UNIVERSAL->cando , shortcut for testing and running methods?
by Rhandom (Curate) on Mar 06, 2009 at 15:14 UTC
    Your examples aren't quite parallel. The first one working with hash assignment uses parallel operations. In the second example you pass a different argument to the second subroutine. If you can afford having real parallelism then there is another option available.
    my $meth = $self->can('home') || $self->can('house') || confess(q{Can' +t determine home}); my $home = $self->$meth(1);
    Which if you were insistent on having be one line could do
    my $home = ($self->can('home') || $self->can('house') || confess(q{Can +'t determine home}))->($self, 1);
    I think the first is more clear.

    Yet another option is:
    my $meth_name = (grep {$self->can($_)} qw(home house))[0] || confess(q +{Can't determine home}); my $home = $self->$meth_name(1);
    However this last option is less optimal in readability and in efficiency.

    my @a=qw(random brilliant braindead); print $a[rand(@a)];

Log In?
Username:
Password:

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: perlquestion [id://748756]
Approved by Corion
Front-paged by Corion
help
Chatterbox?
and the web crawler heard nothing...

How do I use this?Last hourOther CB clients
Other Users?
Others chanting in the Monastery: (4)
As of 2024-04-24 01:39 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found