<> wrote in comp.lang.perl.misc:
> Markus Dehmann wrote:
> > I often find myself typing
> >
> > > unless(defined $x and defined $y and defined $z){ # ... many variables
> > > # ...
> > > }
> >
> > Is there a shorter form to write that? (I mean apart from "&&" for "and").
> >
> > Unfortunately,
> > > unless(defined ($x,$y,$z))
> > does not work.
[...]
> if (3 == grep defined $_, ($x, $y, $z))
> {
> print "World\n";
> }
I'm not too happy with this solution. For one, it must be changed in
two places when the set ($x, $y, $z) changes.
if ( 0 == grep !defined, $x, $y, $z )
is easier to maintain, but it suffers from double negation. Disguising one
negation as "0 ==" helps a little.
Like all grep's it runs through the whole list though the result is clear
after the first undefined element is found. That is inefficient if lists
are long and undefined elements are frequently present. List::Util has
first() to offer, but in this particular case there is a snag. From the
documentation:
first BLOCK LIST
Similar to "grep" in that it evaluates BLOCK setting $_ to each
element of LIST in turn. "first" returns the first element where
the result from BLOCK is a true value. If BLOCK never returns true
or LIST was empty then "undef" is returned.
Now, if we write
first { !defined } $x, $y, $z;
that will return an undefined value, if one is found (of course). It
will also return an undefined value if none is found (BLOCK never returns
true). That is unfortunate and makes first() unusable for this purpose.
If the designer had decided to return empty in the exceptional case,
sub first (&;@) {
my $cond = shift;
$cond->() and return $_ for @_;
return;
}
one could say
0 == (() = first { !defined } $x, $y, $z);
This is somewhat cryptic, but it would be the way to go if efficiency
was critical.
Anno
--
If you want to post a followup via groups.google.com, don't use
the broken "Reply" link at the bottom of the article. Click on
"show options" at the top of the article, then click on the
"Reply" at the bottom of the article headers.