Re: Perl Peeves

Peter J. Holzer wrote:

On 2009-01-29 22:54, Bruce Cook
<bruce-usenet@xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx> wrote:
Peter J. Holzer wrote:
On 2009-01-27 09:08, Eric Pozharski <whynot@xxxxxxxxxxxxxx> wrote:
On 2009-01-27, Tim McDaniel <tmcd@xxxxxxxxx> wrote:
(5) That "special false". I was going nuts trying to figure out what
was different between

[ '' in string context, 0 in numeric context ]

That special false is evaluated to blah-blah-blah *immediately* since
the context is known at compile time (am I right?).

No. Consider:

use warnings;
use strict;

my $bool = (1 < 0);

if (rand() < 0.5) {
print "<$bool>\n";
} else {
print 0 + $bool, "\n";

Anyone who applies a numeric operator to a logical value and expects
consistent results is asking for trouble.

The program above does produce consistent results and is perfectly
well-defined in Perl. I am not asking for trouble, but demonstrating a
perfectly well-defined (though somewhat surprising) property of the
scalar value returned by (1 < 0). (Interestingly, if I change (1 < 0) to
(0 < 1), then I am asking for trouble).

In strongly-typed languages you would get a compiler or run-time
error/warning, however perl is a scripting language and is built to be
flexible, assumes you know what you're doing and will silently oblige
even the most horrendous abuses.

You actually have the same issue in C: false is defined as 0 and true is

However, in C, !0 is defined as 1.

This is where lots of people make mistakes in C.

if(a) is not the same as
if(a == !0)

Original C compilers had an easy way of doing conditionals; they would
assign a variable to a register and then branch on the Z flag. This worked
because !0 is any value with any bit set.

There is no "boolean" type in C (well, C99 has _bool, but ...) and all
the "logical" operators in C return a well-defined result (1 or 0) of
type int.

Yes, there are no bools, but conditionals in C work on zero and non-zero

I have seen a discussion recently where someone was using an
library "elegantly" and came unstuck on a different platform because he
assumed that the true returned from that library was 1 (as it was on his
development platform). His usage became really interesting because the
new platform was returning -1 (binary all 1s), which is another common
value used for true.

This is however a problem with his use of this particular library, not a
problem with his use of C.

x = (1 > 0) + 5;

is perfectly well-defined in C and will always assign 6 to x.

If a function is defined as "returning a true value on success" of
course you cannot test this with if (function() == 1), you need to use
if (function()).

This example would work, however in some C compilers I have used
x=(2>0)+5 would always return 7. This is because the compiler worked with
not 0 being true, and the cheapest comparison on a particular platform is

This doesn't break comparison operators, but does give an unexpected result
when used as an integer result.

As a programmer you need to understand when you're crossing type

And you also need to know when you are *not* crossing type boundaries.
In C (1 > 0) + 5 doesn't cross a type boundary. Both (1 > 0) and 5 are
expressions of type int.

and make sure at that point you force defined behavior the || 0
construct is a good clean way of making sure your falses are actually
integer/cleanly printable.

"actually integer" and "cleanly printable" have nothing to do with each
other. '', 'green', 'false' are all cleanly printable, but none of them
is an integer. The "special false" value is an integer (the integer
zero) and it is also printable (it prints as ''), but depending on your
expectations it may not be "cleanly printable" (a "normal" integer of
value 0 prints as '0', not '').

Sorry, you're mistaking C semantics for Perl. Perl does not treat scalars
as integers and so it's conditionals are more complex (and yes hacky) than
C. Especially the one you don't like, which is defining the behavior of a
string being used in a condition.

Perl implicitly acknowledges data type differences in the fact that it
uses different binary operators for strings vs integers.

Perl has a very precise definition what will be recogized as true and
false. It also has a definition what value (the "special false") will be
returned by the "logical" operators when they return false. For some
reason it doesn't define what these operators return for the true value.
I am very sure that this omission has nothing to do with the
number/string ambivalence of scalars. I tend to think that the omission
is a simple oversight, but it might be loosely defined as "any true
value" on purpose.

Perl defines false and any other value is true. This is not an omission.
In this way it does behave exactly the same way C does.