Here's a quick one. In Perl 5 (might be 5.005, I'm not sure...),
they introduced some new boolean operators, or, and,
not which can be used instead of ||, &&, !
respectively. In an earlier page, I went over
the example:
if ( (($hr < 10) && ($ampm eq 'pm'))
|| (($name1 eq 'Jennifer') && ($name2 eq 'Love')
&& ($name3 eq 'Hewitt'))
|| ($cashBox < 200)) {
&admitGuest();
}
Well, these days, I would do this instead:
if ( (($hr < 10) and ($ampm eq 'pm'))
or (($name1 eq 'Jennifer') and ($name2 eq 'Love')
and ($name3 eq 'Hewitt'))
or ($cashBox < 200)) {
&admitGuest();
}
Similarly, if I was trying to set a default value I might do something like this:
if (! defined($shadingRate)) {
$shadingRate = 0.25;
}
but these days, I would say:
if (not defined($shadingRate)) {
$shadingRate = 0.25;
}
So I think it's pretty much a no-brainer that
or/and/not is more readable than ||/&&/!.
However, there are a few things that you need to be careful about. The main
thing is operator precedence. In an earlier
page I discussed precedence issues and suggested the over-use of
parenthesis () to explicitly declare precedence rather than counting on the
implicit precedence inherent to Perl. This is mainly because I can never
remember what the precedence tables are.
This can actually come back to bite you in weird ways. The big difference here is that or/and/not are the absolute bottom precedence, so any other operator will tend to want to bind first.
Supposing (real life example) you are editing someone's scene browser (in this case, Doug Cooper's) and you want to do something to each file satisfying a certain criterion. Suppose, for example, that you want to do something with all files that satisfy:
$_ variable, but
I was working on someone else's program, and when I do that, I try to emulate
the other person's coding style (unless it excessively annoys me). For that
matter, I still haven't decided whether or not I like putting the grep inside
the iteration array, but that's an issue for another day. One way we could
code our little test is:
foreach my $filename (grep /\.tif$/ && (! -l), @fileList) {
# do something with each filename
}
So what happens if we blindly change out the && with an
and?
foreach my $filename (grep /\.tif$/ and (not -l), @fileList) {
# do something with each filename
}
Well, if you tried to enter that, I believe Perl would actually refuse to
compile. It looks pretty mysterious, but here's what is happening:
and has such low precedence that (not -l) is binding
with the , so that it sees (not -l), @fileList,
which evaluates to the scalar version of the second argument,
@fileList will evaluate to be the number of elements in
@fileList. Then the and comes into play
and evaluates /\.tif$/ and scalar(@fileList), which evaluates to
a scalar. grep, however, requires at least 2 arguments, but
because of the bizarre precedence, we only have 1, so it won't compile.
Of course, this can all be saved with some parenthesis:
foreach my $filename (grep (/\.tif$/ and (not -l)), @fileList) {
# do something with each filename
}
So in summary:
or/and/not now instead of
||/&&/!