short form for (defined $x and defined $y and ... )?

M

Markus Dehmann

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.

Thanks!
Markus
 
U

Uri Guttman

MD> I often find myself typing
then don't type that! i suspect a poor design that makes you check many
variables for defined. i have never seen that in quality code.

what that means is to solve the real problem (why are you doing that)
rather than the 'how do i do this?' problem.

post (a short complete program) that shows why you do all those defined
calls.

uri
 
R

robic0

I often find myself typing


Is there a shorter form to write that? (I mean apart from "&&" for "and").

Unfortunately,
does not work.

Thanks!
Markus

Stop thinking of Perl in a English sentence(y) way.
Even though the very "evil" word *unless* is available,
logic is Boolean! In more understandable terms its called
"Formal Symbolic Logic" and its offered as an elective at
every JC in the country (for 3 credits... whoop!).

Its a course without which, imo, you will run into problems
with the if/then/else construct. Btw, that course takes you
through the analysis of English sentences, then paragraphs,
then documents, where you have to write symbolic logic
expressions, turn English into logic, then for the grand
finally, you have to solve the logic equations just written
to give an overall TRUTH to the statement/paragraph/document.
Oh and there are the FORMAL ERRORS you have to deliniate.
20 or so. If you don't get an 'A' in this course there could
be trouble with programming.

"Shorter" is not better. Never was and never will be.
Shorthand notation you see on the usenet group are willfull
attempt to mislead. Deception is actually power here.

There is *NO* hidden logic, manifested by notation or keywords,
that make the code work faster or better beyond the fully
exposed if/then/else construct.

You actually have to "break the code down into simple logic"
before it can be optimized. If it can't be optimized when
expressed simply, then it *CANNOT* be optimized anyway else !!!

Hope you understand that?

robic0
 
A

attn.steven.kuo

Markus said:
I often find myself typing


Is there a shorter form to write that? (I mean apart from "&&" for "and").

Unfortunately,
does not work.


Perhaps you have a preference between these two:

use List::MoreUtils qw/all/;

# ...

if (all { defined $_ } ($x, $y, $z))
{
print "Hello ";
}

# or

if (3 == grep defined $_, ($x, $y, $z))
{
print "World\n";
}
 
R

robic0

Perhaps you have a preference between these two:

use List::MoreUtils qw/all/;

# ...

if (all { defined $_ } ($x, $y, $z))
{
print "Hello ";
}

# or

if (3 == grep defined $_, ($x, $y, $z))
{
print "World\n";
}

I've seen it all now, the whole thing. No need to wonder on
my death bed. An actual reference to a module that does the
&& for you. Thats pretty close to "lets all just take drugs
and get drunk". No need to program ever again.

Hey! Wheres my goddammed Perl program that does my programming?
Where'd I put that damned thing........ jeez!

robic0
 
M

Markus Dehmann

Uri said:
MD> I often find myself typing

then don't type that! i suspect a poor design that makes you check many
variables for defined. i have never seen that in quality code.

what that means is to solve the real problem (why are you doing that)
rather than the 'how do i do this?' problem.

post (a short complete program) that shows why you do all those defined
calls.

my ($x,$y,$z) = $userInput =~ m/(.+?)\s\+\s(.+?)\s=\s(.+)/;
die("wrong input format") unless(defined $x and defined $y and defined $z);

I write lots of little scripts like that match user input like this.
Sure, it's not "quality code", but it's definitely not worth to spend
more code on the user input error checking for my purposes. So, if I
grep, say, 10 variables from the user input this (defined $x and defined
....) can be a little longish. I'd just like to say (defined ($x,$y,$z,...))

Okay, but you're right, maybe I could change the design. Maybe something
like this:

if( $userInput =~ m/(.+?)\s\+\s(.+?)\s=\s(.+)/ ){
($x,$y,$z) = ($1,$2,$2);
}
else{
die("wrong input format");
}

But again, this is longer, and I find my first version more intuitive.

Markus
 
A

A. Sinan Unur

if( $userInput =~ m/(.+?)\s\+\s(.+?)\s=\s(.+)/ ){
($x,$y,$z) = ($1,$2,$2);
}
else{
die("wrong input format");
}

But again, this is longer, and I find my first version more intuitive.

$userInput =~ m/(.+?)\s\+\s(.+?)\s=\s(.+)/ or die "...";
my ($x, $y, $z) = ($1, $2, $3);

Sinan
 
A

Anno Siegel

Markus said:
I often find myself typing


Is there a shorter form to write that? (I mean apart from "&&" for "and").

Unfortunately,
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
 
A

attn.steven.kuo

Anno said:
[...]

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.

[ ... ]



Ah, makes perfect sense . I hadn't thought about the
aspect of efficiency. Perhaps then I'd use the firstidx
function from List::MoreUtils.

Taking a peek at the XS source code for firstidx:

http://search.cpan.org/src/VPARSEVAL/List-MoreUtils-0.19/MoreUtils.xs

I see a "break" out of the "for" loop, so this need not evaluate
more arguments than necessary:


if ( (firstidx { !defined } ($x, $y, $z) ) < 0 )
{
# do something...
}
 
A

Anno Siegel

Anno said:
[...]


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.

[ ... ]



Ah, makes perfect sense . I hadn't thought about the
aspect of efficiency. Perhaps then I'd use the firstidx
function from List::MoreUtils.

Oh, good. Must have missed that in List::MoreUtils.

[...]
if ( (firstidx { !defined } ($x, $y, $z) ) < 0 )

Aha. That's it then.

Unlike Uri, occasionally I do want to verify that all members of a list
(or an array) are defined. I found the behavior of List::Util::first
less than satisfactory in that regard. Nice to know about firstidx.

Anno
 
U

Uri Guttman

MD> my ($x,$y,$z) = $userInput =~ m/(.+?)\s\+\s(.+?)\s=\s(.+)/;
MD> die("wrong input format") unless(defined $x and defined $y and defined $z);

first rule, always check regexes for success before you use the
values. other replies have shown how to do this.

now let's look at that regex. all the grabs are .+'s which means they
all have at least one char and nothing is optional so they all must grab
something if the whole regex matches. that means you can't get an undef
grabbed value if that regex matches. so your defined checks are
redundant and can be removed provided you check the regex for
success. so i was right about your checking defined on all of them.

my ($x,$y,$z) = $userInput =~ m/(.+?)\s\+\s(.+?)\s=\s(.+)/ or
die 'lousy input' ;

look mommy! no calls to defined! :)

MD> Okay, but you're right, maybe I could change the design. Maybe
MD> something like this:

MD> if( $userInput =~ m/(.+?)\s\+\s(.+?)\s=\s(.+)/ ){
MD> ($x,$y,$z) = ($1,$2,$2);
MD> }
MD> else{
MD> die("wrong input format");
MD> }

MD> But again, this is longer, and I find my first version more intuitive.

or look at my version above. when you do something very simple based on
a boolean, then condtional modifiers (trailing if/unless) or boolean ops
(and, or ) are cleaner. they also save blocks which cost something to
enter. and extra indents and {} waste pixels and those are a precious
resource!

uri
 
U

Uri Guttman

AS> Unlike Uri, occasionally I do want to verify that all members of a
AS> list (or an array) are defined. I found the behavior of
AS> List::Util::first less than satisfactory in that regard. Nice to
AS> know about firstidx.

i just design so that isn't needed. not too hard i think. there are many
ways of doing things and i try to spend more time picking ones which
don't make me code stuff like that (and other constructs i don't
like. :)

uri
 
J

Joe Smith

Markus said:
my ($x,$y,$z) = $userInput =~ m/(.+?)\s\+\s(.+?)\s=\s(.+)/;
die("wrong input format") unless(defined $x and defined $y and defined $z);

Others have shown you the proper way to do it, but I want to point out that
die "wrong input format" unless defined $z;
would handle it. If $z is defined, then there is no need to test $x or $y
since they will be defined (even if they are null strings).
-Joe
 
B

Bart Lateur

Markus said:
I often find myself typing


Is there a shorter form to write that? (I mean apart from "&&" for "and").

Invert the condition, and search for an undefined item.

if(grep !defined, $x, $y, $z) { ... }
 
A

Anno Siegel

Joe Smith said:
Others have shown you the proper way to do it, but I want to point out that
die "wrong input format" unless defined $z;
would handle it. If $z is defined, then there is no need to test $x or $y
since they will be defined (even if they are null strings).

They can't be "null" strings (the common term is "empty") because all
captures have a "+" in it. Also, $z isn't special. If any one of the
captures is set, all will.

But using that test would require the reader to understand what the content
of one match has to say about the content of the others. It is much clearer
to test if the regex has matched at all and then just use the captures.

Anno
 
R

robic0

AS> Unlike Uri, occasionally I do want to verify that all members of a
AS> list (or an array) are defined. I found the behavior of
AS> List::Util::first less than satisfactory in that regard. Nice to
AS> know about firstidx.

i just design so that isn't needed. not too hard i think. there are many
ways of doing things and i try to spend more time picking ones which
don't make me code stuff like that (and other constructs i don't
like. :)

uri

You insinuate a higher intelligence design while using code other folks program...
Pretty soon you won't need to code at all.
And I'm being quite literal. Knowledge of usage of other ppl's code is what your
trying to master whithout knowing the methods.
Doesn't it nagg your brain when people have to write code for you because your
too lazy or stupid to do it yourself?

robic0
 
R

robic0

MD> my ($x,$y,$z) = $userInput =~ m/(.+?)\s\+\s(.+?)\s=\s(.+)/;
MD> die("wrong input format") unless(defined $x and defined $y and defined $z);

first rule, always check regexes for success before you use the
values. other replies have shown how to do this.
Why advise sucess checking? One liners are encoraged here.
now let's look at that regex. all the grabs are .+'s which means they
all have at least one char and nothing is optional so they all must grab
something if the whole regex matches. that means you can't get an undef
grabbed value if that regex matches. so your defined checks are
redundant and can be removed provided you check the regex for
success. so i was right about your checking defined on all of them.

Any regex, if successfull will have defined values, absent 'or's (|).
Within or's (|), after sucessfull regex, its only necessary to check a
single define within an 'or' block.
Its essence is badly designed because of the 1 liners so much promoted
in this group.
my ($x,$y,$z) = $userInput =~ m/(.+?)\s\+\s(.+?)\s=\s(.+)/ or
die 'lousy input' ;

look mommy! no calls to defined! :)

MD> Okay, but you're right, maybe I could change the design. Maybe
MD> something like this:

MD> if( $userInput =~ m/(.+?)\s\+\s(.+?)\s=\s(.+)/ ){
MD> ($x,$y,$z) = ($1,$2,$2);
MD> }
MD> else{
MD> die("wrong input format");
MD> }

MD> But again, this is longer, and I find my first version more intuitive.

or look at my version above. when you do something very simple based on
a boolean, then condtional modifiers (trailing if/unless) or boolean ops
(and, or ) are cleaner. they also save blocks which cost something to
enter. and extra indents and {} waste pixels and those are a precious
resource!

uri
Jeez, so you know 'cleaner' code. Care to explain what that means..

robic0
 
R

robic0

Others have shown you the proper way to do it, but I want to point out that
die "wrong input format" unless defined $z;
would handle it. If $z is defined, then there is no need to test $x or $y
since they will be defined (even if they are null strings).
-Joe

Well yes Joe, your right, and good point.
robic0
 
R

robic0

They can't be "null" strings (the common term is "empty") because all
captures have a "+" in it. Also, $z isn't special. If any one of the
captures is set, all will.

But using that test would require the reader to understand what the content
of one match has to say about the content of the others. It is much clearer
to test if the regex has matched at all and then just use the captures.

Anno

But in abscence of '|' group, all matches are defined, allbeit empty $'vars.
so his unless block will always be perfectly valid, on whole, given its design defficiencies.
But for his purposes it does what he wants. There are no benchmark code inefficiencies to
show in this example.

Correct style, not intent.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,769
Messages
2,569,581
Members
45,057
Latest member
KetoBeezACVGummies

Latest Threads

Top