Perl Peeves

T

Tim McDaniel

Just venting.

(1) I hate that

Unary "+" has no effect whatsoever, even on strings.

(per "man perlop"). Unary plus LOOKS like a unary arithmetic
operator, like "-". I was using it like "+@a", as a shorter form of
"scalar @a", until I finally found the above statement in the 5.010000
man page and realized that "+@a" was working only because I happened
to be using it in a scalar context already.

(I could do "- -@a", but that's just not as elegant as "+@a" would be.)

(2) That had effect but wasn't documented in "man perlop" in 5.005,
the version on my ISP's shell accounts.

(3) "man perlop" has

Binary "<" returns true if the left argument is numerically less
than the right argument.

et cetera, but it doesn't even mention "false" in that context and
doesn't define "true". I finally tracked down the definition not in
"man perlop", but in "man perlsyn":

Truth and Falsehood

The number 0, the strings '0' and '', the empty list "()", and
"undef" are all false in a boolean context. All other values are
true. Negation of a true value by "!" or "not" returns a special
false value. When evaluated as a string it is treated as '', but
as a number, it is treated as 0.

(4) It doesn't say which true value is returned. It could return
'0 ', it appears, and too bad if you happen to do arithmetic on it or
print it without output delimiters. And it doesn't say that the
relational operators ever return false, much less that it's the
special false.

(5) That "special false". I was going nuts trying to figure out what
was different between

$ perl -w -e 'my $j = (17 < 5); print "<$j>\n"'
<>

$ perl -w -e 'my $j = 0+(17 < 5); print "<$j>\n"'
<0>

$ perl -w -e 'my $j = 0+("" ); print "<$j>\n"'
Argument "" isn't numeric in addition (+) at -e line 1.
<0>

(6) The stupidity that I've mentioned before, of the -r / -w / -x
being defined as being ignorant of ACLs, when they should truly follow
their definitions in "man perlfunc":

-r File is readable by effective uid/gid.
-w File is writable by effective uid/gid.
-x File is executable by effective uid/gid.
 
J

Jürgen Exner

Just venting.

(1) I hate that

Unary "+" has no effect whatsoever, even on strings.

Agree, that is not very user friendly.
(3) "man perlop" has

Binary "<" returns true if the left argument is numerically less
than the right argument.

et cetera, but it doesn't even mention "false" in that context

Well, ok, wording might be better as
"... returns true if and only if the left argument..."
No big deal. Most people will understand it that way anyway.
doesn't define "true".

Why should it? There is no point in repeating the definition of true for
every single operator or function that returns a boolean value.
(4) It doesn't say which true value is returned.

Why should it? True is true is true. As a programmer you really don't
care about its implementation by the compiler.
(5) That "special false". I was going nuts trying to figure out what
was different between

$ perl -w -e 'my $j = (17 < 5); print "<$j>\n"'
<>

$ perl -w -e 'my $j = 0+(17 < 5); print "<$j>\n"'
<0>

Why on earth would you do something like that? It is not logical (and a
_VERY_ bad practice carried over from C) to add a number and a boolean
value? What + operator and what algebra is that supposed to be?
Operators for boolean values are e.g. and, or, ||, not.
Granted, Perl does a lot of implicit type conversions or rather any
scalar automatically has numerical, boolean, and text values. But if you
make use of them, then you better know exactly what they do, e.g. what
is the value of
5 + "Hello World"
or
"The answer is 42" + 9
$ perl -w -e 'my $j = 0+("" ); print "<$j>\n"'
Argument "" isn't numeric in addition (+) at -e line 1.

Good! Exactly as it is supposed to be.
(6) The stupidity that I've mentioned before, of the -r / -w / -x
being defined as being ignorant of ACLs, when they should truly follow
their definitions in "man perlfunc":

Yeah, you got a point. Feel free to submit a patch.

jue
 
T

Tad J McClellan

Tim McDaniel said:
Just venting.

(4) It doesn't say which true value is returned.


Because the programmer does not need do know.

You only need to know if it is one of the true values or one of the false values.

It could return
'0 ', it appears,


Yes, it could.

And the true value that it returns with today's perl version
may be different from the true value that it returns in
the next perl version.

It is not specified, so code that relies on it being a particular
value is bad code.

and too bad if you happen to do arithmetic on it or


Bad things happen when you use numeric operators with boolean operands.

That is supposed to be surprising?
 
T

Tim McDaniel

Well, ok, wording might be better as
"... returns true if and only if the left argument..."
No big deal. Most people will understand it that way anyway.

Hey, I did say "Peeves", not "Self-Evident Perl Bugs".
Why should it? There is no point in repeating the definition of true
for every single operator or function that returns a boolean value.

I think "true" and "false" could be logically defined in perlop --
hey, they're actually computed by operators there -- than in perlsyn.
So I'd move the paragraph from perlsyn to perlop, or copy it, or at
least have one place point to the other.
Why on earth would you do something like that?

If I want to write it to a properties file to be read in again later,
or to output it for debugging.
my $output_value = (CONDITION) ? 1 : 0;
just feels amateurish and too verbose to me.
It is not logical (and a _VERY_ bad practice carried over from C) to
add a number and a boolean value? What + operator and what algebra is
that supposed to be?

"As you know, Bob" (you allude to it later), Perl 5 doesn't have a
boolean type, but uses strings and integers. So they can't go
preaching type purity to me. If there *were* a boolean type built in,
I'd quite agree with you.
Granted, Perl does a lot of implicit type conversions or rather any
scalar automatically has numerical, boolean, and text values. But if
you make use of them, then you better know exactly what they do

and I think it should at least be consistent with the rest of the
language. I'd like 1 versus 0, or -1 versus 1, or 1 versus a real ''
(though that looks weird).
Yeah, you got a point. Feel free to submit a patch.

Given that it was long-since defined in the man pages, and given that
there's a partial workaround with a pragma, it would probably be
rejected.
 
T

Tim McDaniel

Just venting.

(1) I hate that

Unary "+" has no effect whatsoever, even on strings.

(per "man perlop"). Unary plus LOOKS like a unary arithmetic
operator, like "-". ...

(I could do "- -@a", but that's just not as elegant as "+@a" would
be.)

Of course, "0+@a" would work as well as "scalar @a", but none of the
choices really look elegant.
 
T

Tim McDaniel

Because the programmer does not need do know.

You only need to know if it is one of the true values or one of the
false values.

Then why do the man pages define it?
 
U

Uri Guttman

JE> Agree, that is not very user friendly.

unless you use it as intended which is to disambiguate parsing issues
like print (3 + 4) * 5 vs print +(3 + 4) * 5.

JE> Why should it? There is no point in repeating the definition of true for
JE> every single operator or function that returns a boolean value.

perl defines the set of false values. all others are true. this is a
good concept.

JE> Why on earth would you do something like that? It is not logical (and a
JE> _VERY_ bad practice carried over from C) to add a number and a boolean
JE> value? What + operator and what algebra is that supposed to be?
JE> Operators for boolean values are e.g. and, or, ||, not.
JE> Granted, Perl does a lot of implicit type conversions or rather any
JE> scalar automatically has numerical, boolean, and text values. But if you
JE> make use of them, then you better know exactly what they do, e.g. what
JE> is the value of
JE> 5 + "Hello World"
JE> or
JE> "The answer is 42" + 9

agreed. boolean values should be used in boolean contexts. if you decide
to use a false value in string or numeric contexts it will be coerced as
desired without a warning. this is also true for undef which is false
but this will trigger a warning.

JE> Yeah, you got a point. Feel free to submit a patch.

perl derived its -rwx ops from the original unix file modes. this was
way before any system that perl was on had ACL's. there is no easy way
to retrofit acl's onto such a simple API.

uri
 
E

Eric Pozharski

Just venting.

oh, come on, just get used to it.

*SKIP*
(5) That "special false". I was going nuts trying to figure out what
was different between

Lots of things
$ perl -w -e 'my $j = (17 < 5); print "<$j>\n"'
<>

{4185:3} [0:29]$ perl -mO=Deparse -wle 'my $j = (17 < 5); print "<$j>"'
BEGIN { $^W = 1; }
BEGIN { $/ = "\n"; $\ = "\n"; }
my $j = !1;
$ perl -w -e 'my $j = 0+(17 < 5); print "<$j>\n"'
<0>

{4192:4} [0:0]$ perl -mO=Deparse -wle 'my $j = 0+(17 < 5); print "<$j>"'
BEGIN { $^W = 1; }
BEGIN { $/ = "\n"; $\ = "\n"; }
my $j = 0;
$ perl -w -e 'my $j = 0+("" ); print "<$j>\n"'
Argument "" isn't numeric in addition (+) at -e line 1.
<0>

That special false is evaluated to blah-blah-blah *immediately* since
the context is known at compile time (am I right?). (just out of
curiosity, what that "special false" would evaluate in void context?)

{7152:24} [0:0]$ perl -mO=Deparse -wle '(17 < 5); print "<$j>"'
Name "main::j" used only once: possible typo at -e line 1.
BEGIN { $^W = 1; }
BEGIN { $/ = "\n"; $\ = "\n"; }
'???';
print "<$j>";
-e syntax OK

he-he, it bails out
(6) The stupidity that I've mentioned before, of the -r / -w / -x
being defined as being ignorant of ACLs, when they should truly follow
their definitions in "man perlfunc":

-r File is readable by effective uid/gid.
-w File is writable by effective uid/gid.
-x File is executable by effective uid/gid.

"Patches are welcome" (c)
 
T

Tad J McClellan

Tim McDaniel said:
Then why do the man pages define it?


So that the programmer will be able to tell if it is one of the true
values or one of the false values.
 
T

Tad J McClellan

Tim McDaniel said:
Of course, "0+@a" would work as well as "scalar @a", but none of the
choices really look elegant.


"scalar @a" seems plenty elegant to me.

"short" or "tricky" does not imply "elegant".
 
T

Tad J McClellan

Tim McDaniel said:
I think "true" and "false" could be logically defined in perlop --
hey, they're actually computed by operators there -- than in perlsyn.


But they are most commonly used with "if", "while", etc. and
_those_ are described in perlsyn.

So I'd move the paragraph from perlsyn to perlop,


Then the other half of people will be peeved that is is not described
near the constructs that use it.

or copy it,


Then you would need to keep the 2 copies in sync, and that is asking
for discrepancies to creep in.

or at
least have one place point to the other.


That seems a very good idea to me.
 
T

Tad J McClellan

Uri Guttman said:
JE> Agree, that is not very user friendly.

unless you use it as intended which is to disambiguate parsing issues
like print (3 + 4) * 5 vs print +(3 + 4) * 5.


One of _my_ pet peeves is using it to disambiguate parsing issues. :)

I would prefer to use parens around the function's arg list even if
I don't normally choose to use parens around arg lists.

print((3 + 4) * 5)
 
P

Peter Scott

If I want to write it to a properties file to be read in again later, or
to output it for debugging.
my $output_value = (CONDITION) ? 1 : 0;
just feels amateurish and too verbose to me.

Yes, this annoyed me too, that naive attempts to freeze and thaw boolean
results can fail because false is rendered as the empty string. I
don't know why they didn't pick "0". On the other hand, one of the more
natural choices - values separated by commas - does work fine:

$ perl -wle 'my ($x,$y,$z) = split /,/, "42,,"; print $y ? "True" :
"False"'

which is probably why we don't hear much complaint.

However, if you're in the business of serializing things these days, it's
not long before you realize you should be using something like
Data::Dumper because of the possibility of references, and at that point
it doesn't matter what the representation of false is.
Given that it was long-since defined in the man pages, and given that
there's a partial workaround with a pragma, it would probably be
rejected.

It's been discussed recently on P5P. As an AFS user, I run into this
problem frequently, but it's all kinds of programs that are unaware of
ACLs. A patch to test ACLs should work for both POSIX and AFS ACLs (the
Perl installation script is AFS-aware, after all), and I think it's quite
hard to write such a patch without it impacting performance across the
board. Have a go at it and let us know whether you still think its
absence should be characterized as "stupid".
 
T

Tim McDaniel

JE> Agree, that is not very user friendly.

unless you use it as intended which is to disambiguate parsing issues
like print (3 + 4) * 5 vs print +(3 + 4) * 5.

While this particular case could be handled via print((3 + 4) * 5),
are there cases that an extra set of parens can't handle?
Maybe cases with a leading "{"?
 
T

Tim McDaniel

So that the programmer will be able to tell if it is one of the true
values or one of the false values.

But you said that the programmer doesn't need to know. And it *is*
true that if all you do with a conditional operator is use it in a
conditional context (?:, if, while, whatever), you don't need to know
its values.
 
J

Jürgen Exner

Uri Guttman said:
JE> Agree, that is not very user friendly.

unless you use it as intended which is to disambiguate parsing issues
like print (3 + 4) * 5 vs print +(3 + 4) * 5.

Well, I'd rather use paranthesis for that purpose. They are less
cryptic.

Either way, if unary + were to act like the unary -, i.e. evaluating its
argument as a scalar and returning the numerical value of it, that would
be more consistent with at least my intuitive expectations.
And I think it would not break your smart parsing scheme, either.

jue
 
U

Uri Guttman

JE> Well, I'd rather use paranthesis for that purpose. They are less
JE> cryptic.

JE> Either way, if unary + were to act like the unary -, i.e. evaluating its
JE> argument as a scalar and returning the numerical value of it, that would
JE> be more consistent with at least my intuitive expectations.
JE> And I think it would not break your smart parsing scheme, either.

a numeric coercing leading + would return 0 for most strings (or the
value of leading digits). i rarely if ever use unary + but i don't see
any reason to change it. 0+EXPR will coerce as you want and so will
''.EXPR. but as we have covered many times, explicit coercion is rarely
needed in perl. i have seen cases where unary + was a good thing for
disambiguation but i can't recall them now. anyhow, it is a minor issue
and not worthy of a long thread.

uri
 
E

Eric Pozharski

While this particular case could be handled via print((3 + 4) * 5),
are there cases that an extra set of parens can't handle?
Maybe cases with a leading "{"?

Consider giving up idea that C<+> is "unary plus". It's not. It's a
special that hints B<perl> that's an expression that comes next.
C<perldoc -f map> has more.
 
A

A Dude

[Perl] doesn't define "true".  
Why should it? There is no point in repeating the definition of true
for every single operator or function that returns a boolean value.

If I want to write it to a properties file to be read in again later,
or to output it for debugging.
    my $output_value = (CONDITION) ? 1 : 0;
just feels amateurish and too verbose to me.[/QUOTE]

Then write (the perlish way)

my $output_value = CONDITION || '0';

or

printf "SHOULD_I_OUTPUT=%s\n", ( CONDITION || '0' );
[...] Perl 5 doesn't have a
boolean type, but uses strings and integers.  So they can't go
preaching type purity to me.  

Like most things in Perl, it's an implicit thing. Most of the time
you'll be dealing with

if ( $my_value < 17 ) { ...

or
do_something_else() unless $command eq 'proceed';


But if you have to capture a condition, name your boolean variables
obvious names like

$name_is_ambiguous

You were talking about one specific case, which can be addressed. As
for output

$my_boolean=

is illustrative to me. (Unless it might be a ' ')

But if you use Data::Dumper or Smart::Comments, it won't be an issue.

I'm with Jurgen. It doesn't need it. And along with that, if you're
going to use it in computations:

my $sign = -1 ** ( $my_var < 10 ? 1 : 0 );

doesn't look as much like c-hack, and explicitly transforms the
boolean condition to the value you think you're getting in the first
place.
 
T

Tim McDaniel

Jürgen Exner   said:
[Perl] doesn't define "true".

That's an incorrect summary. "man perlsyn" defines it. "man perlop"
is where I expected it, with the conditional operators that return
true or false. "man perlop" doesn't define it, and doesn't point at
"man perlsyn" or anywhere else to define it.
Then write (the perlish way)

my $output_value = CONDITION || '0';

That depends on knowing that a conditional operator that evaluates to
true is 1, and I had some little trouble finding that definition.
As for output

$my_boolean=

is illustrative to me. (Unless it might be a ' ')

Or "\t" or whatever. (Looking at that, I wouldn't be sure that I
didn't forget to actually print $my_boolean.) (And, of course, if
it's read in again, it's not the special false value unless I !! it or
something.)
But if you use Data::Dumper or Smart::Comments, it won't be an
issue.

As it happens, at the moment I'm writing scalars to properties files,
but I'll keep that in mind if I'm dumping general data structures.
 

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,989
Messages
2,570,207
Members
46,782
Latest member
ThomasGex

Latest Threads

Top