automatic number <-> string conversions

R

Rainer Weikusat

Coming to think of this, I'd agree that automatically converting a
non-numerical string to a number with value zero is rarely useful and
likely to lead to unpleasnt surprises, eg

[rw@sable]/tmp#perl -e 'print "David" == "Nick", "\n"'
1

(although this could be referred to 'deeper insight')

That's consistent with how atoi/ strtol would behave,

-----------
#include <stdlib.h>
#include <stdio.h>

int main(void)
{
printf("%d\n", atoi("Salad") == atoi("Steak"));
return 0;
}
----------

but that's more likely to be an 1970s implemenetation shortcut than a
conscious semantic choice and in any case, someone who knows Perl won't
necessarily/ shouldn't need to know C as well.

OTOH, I think the so-called 'undefined value', at least insofar it is
used as default value of an uninitialized variable, should be an
exception here: A variable with 'no value' should behave as if it had
some 'neutral value' for the context it is used in: Explicit
initialization should only be necessary when something other like than
this 'neutral value' is needed. Forcing people to write

my $a;
$a = 0;
print($a + 1);

instead of

my $a
print($a + 1);

just clutters the code with a lot of 'self-evident' statements.
 
R

Rainer Weikusat

[...]
[rw@sable]/tmp#perl -e 'print "David" == "Nick", "\n"'
1

(although this could be referred to 'deeper insight')

Silly joke I can resist ATM: This works even nicer in German because
"beides Nullen" (both zeroes) is colloquial for "guys who can't get
anything done because it is beyond them" :->
 
C

Charles DeRykus

[...]
[rw@sable]/tmp#perl -e 'print "David" == "Nick", "\n"'
1

(although this could be referred to 'deeper insight')

Silly joke I can resist ATM: This works even nicer in German because
"beides Nullen" (both zeroes) is colloquial for "guys who can't get
anything done because it is beyond them" :->

At least perl warns when "beides Nullen" is "beyond the pale":

perl -wE 'print "David" == "Nick"'
Argument "Nick" isn't numeric in numeric eq (==) at -e line 1.
....
 
C

Charles DeRykus

atoi has no choice: it has to return some int or other to signal
'invalid input', and it's obviously going to return the same one for
different invalid inputs. Since int doesn't have a NaN value, the return
values are going to be equal.


I agree. Uninit value warnings were much more useful in the pre-strict
days when an unexpected undef often meant you had autocreated a variable
without meaning to. These days "uninitiailisized" is the warning
category I turn off most often (the next is probably "exiting").

But, IIUC, I'm not sure how Perl could thread the twisty-turny maze to
warn sanely but not annoyingly.

Sensibly in lvalue settings, it doesn't: 'my $x; say ++$x;'
or: 'my $x; $x .= "foo";

But, most of the time, it seems to me there's more likely a need for a
warning than not, eg,

'my $x; my $y = "Alice hates $x...and the Red Queen;"

If there were no warning because "nothing other than its neutral value
is needed for the context it is used in", it'd fail to alert the author
to expressions that had changed in havoc-wreaking ways computationally
(or semantically).
 
R

Rainer Weikusat

Charles DeRykus said:
Quoth Rainer Weikusat <[email protected]>:
[...]
I agree. Uninit value warnings were much more useful in the pre-strict
days when an unexpected undef often meant you had autocreated a variable
without meaning to. These days "uninitiailisized" is the warning
category I turn off most often (the next is probably "exiting").

But, IIUC, I'm not sure how Perl could thread the twisty-turny maze to
warn sanely but not annoyingly.

Sensibly in lvalue settings, it doesn't: 'my $x; say ++$x;'
or: 'my $x; $x .= "foo";

But, most of the time, it seems to me there's more likely a need for a
warning than not, eg,

'my $x; my $y = "Alice hates $x...and the Red Queen;"

If there were no warning because "nothing other than its neutral value
is needed for the context it is used in", it'd fail to alert the
author to expressions that had changed in havoc-wreaking ways
computationally (or semantically).

Simple. Warn if a string without leading digits is implicitly converted
to a 0. Don't warn if 'an undefined value' is used as if somebody
thought he wasn't accessing some a C 'stack-allocated object' which was
left unitialized for performance reason because that's totally
ridicolous for perl, anyway, and not true. Not everything which has
always worked in this way since 1973 for reasons we've long stopped to
care about has to continue to work in this way. That's going to be a
good idea in certain cases and a bad idea in certain other cases and
*for me*, the benefits outweigh the drawbacks.
 
C

Charles DeRykus

....


IMHO with properly scoped variables an undef is no more likely to be a
mistake than any other value. IME undef warnings cause more problems (in
terms of unnecessary code to work around them) than they solve. A simple
example would be something like this:

my $verb = $conf{verbose} + $ENV{FOO_VERBOSE} + $opt{v};

where silently treating a nonexistent setting as 0 is the right thing to
do. With undef warnings turned on that line of code has to become a good
bit more complex, to no real advantage.

Maybe it's a personal bias bordering on an OCD affliction, but I'd
rather see that as: my $verb = ... + ($ENV{FOO_VERBOSE} // 0) + ...

IMO not appallingly tedious and documenting clearly what's going on.
In that particular case an empty string makes no more sense than an
undef, but an empty string won't warn. In the general case, there are a
great many possible wrong values in any given situation, and undef is no
more likely to be one of them than anything else.

Right. But, IMO, particularly in early development, you're more likely
to forget to initialize and -w can really help. Then you graduate to
more refined types of mayhem and no one can help you.
 
P

Peter J. Holzer

IMHO with properly scoped variables an undef is no more likely to be a
mistake than any other value.

I disagree with that estimation. Undef is much more likely to be a
mistake than any other value because it *means* "no value". So when I
expect a numerical value, 23 may or may not be a mistake, but undef is
certain to be one - because I expect a numerical value and undef isn't
that.

Of course that depends on your coding style. If you treat undef like 0
or an empty string, the warning is just annoying and not helpful at all.
But the way I code, an undef in a place where I didn't expect it almost
always means that there is an error in my logic.

That said, uninitialized is also the warning category I turn off most
often (and I probably mistype it just as often as you ;-)), although
usually in a very tight scope and often around debug output.

Especially for debug output a way to replace it with something else than
"" would be handy, for example something like this:


my $foo = "bla";
my $bar;
{
local $^@ = "(undef)";
say "foo=$foo bar=$bar"
}

could print

foo=bla bar=(undef)


IME undef warnings cause more problems (in
terms of unnecessary code to work around them) than they solve. A simple
example would be something like this:

my $verb = $conf{verbose} + $ENV{FOO_VERBOSE} + $opt{v};

I think I would write that as

my $verb = $conf{verbose} // $ENV{FOO_VERBOSE} // $opt{v};

(or probably the other way around).

hp
 
R

Rainer Weikusat

Peter J. Holzer said:
IMHO with properly scoped variables an undef is no more likely to be a
mistake than any other value.

I disagree with that estimation. Undef is much more likely to be a
mistake than any other value because it *means* "no value".
[...]

Of course that depends on your coding style. If you treat undef like 0
or an empty string, the warning is just annoying and not helpful at
all.

If someone treats Perl like C (or C++ or Java, FWIW) with respect to not
otherwise initialized my variables, that is, assigning values to them
even although automatic conversion of 'undef' to a suitable type would
result in the same value, then, 'undef' being used instead of some
'defined value' should rarely[*] ever happen. But Perl isn't C and it
doesn't suffer from the 'bad habit' of making storage locations
available to code while leaking whatever value the most recent user of
this storage location happened to leave there: Variables created with my
are not uninitialized and I consider the fact that they will 'behave
themselves' according to the ways they're used in a feature (and a very
convenient one at that).

[*] There's still the issue that some builtin functions return undef as
'false value' and that using 0 and 1 in order to mean 'true' and 'false'
can be convenient because it is possible to do ordinary arithmetic with
'boolean values', eg (contrived example)

my $results;

$result = call_a();
$result |= call_b();
$result |= call_c();
print("Something worked!\n") if $result;
 
R

Rainer Weikusat

Charles DeRykus said:
Maybe it's a personal bias bordering on an OCD affliction, but I'd
rather see that as: my $verb = ... + ($ENV{FOO_VERBOSE} // 0) + ...

IMO not appallingly tedious and documenting clearly what's going on.

This would in itself warrant some 'clear documentation' a la

# silence 'undefined value' warnings

because on its own, it's just apparently useless code.
 
C

Charles DeRykus

...

This would in itself warrant some 'clear documentation' a la

# silence 'undefined value' warnings

because on its own, it's just apparently useless code.

If someone knows it's "useless code", I will wager he/she knows well
the dark kingdom of "uninitialized value". (if not, then some lessons
need to be experienced and having been so, you will not want to comment
on such things ever again :)
 
R

Rainer Weikusat

Ben Morrow said:
[undef warnings]
[...]
Don't warn if 'an undefined value' is used as if somebody
thought he wasn't accessing some a C 'stack-allocated object' which was
left unitialized for performance reason because that's totally
ridicolous for perl, anyway, and not true.

I'm pretty certain that wasn't the reason. The warning was added in perl
2 (and goodness me, perl was a lot simpler in those days!); the only
comments about it still preserved in the perl repo are this paragraph in
the manpage:

.B \-w
prints warnings about identifiers that are mentioned only once, and
scalar variables that are used before being set.
Also warns about redefined subroutines, and references to undefined
subroutines and filehandles.

and this comment from the git commit message for perl-2.0, which I
believe was taken from a release announcement of some sort:

* Warnings are now available (with -w) on use of uninitialized
variables and on identifiers that are mentioned only once, and on
reference to various undefined things.

Both of these (and the fact that the message is about an 'uninitialized'
rather than an 'undefined' value) lead me to believe that the intention
was to catch variables created by mistake (through typos and such)
rather than because of any illusions about Perl behaving like C.

'Variables created by mistake' should be caught by the '... used only
once: possible typo at line ...' check and 'strict vars' is IMHO a
better way to guard against that because 'systematic' typos (repeated
identical misspellings) are not uncommon. It is conceivable that the
undef check was meant to be a supplement to the other. OTOH, I consider
it completely probable that this was just another someone with a
automatic "****! That's a PROBLEM!" reaction, especially considering
that 'uninitialized variables' can cause really nasty runtime problems
in C, eg, write accesses through pointer which aren't really dangling
because they point to something completely different than what a naive
observer would assume.
 
R

Rainer Weikusat

Charles DeRykus said:
If someone knows it's "useless code", I will wager he/she knows well
the dark kingdom of "uninitialized value". (if not, then some
lessons need to be experienced and having been so, you will not want
to comment on such things ever again :)

Which "dark kingdom"? Assuming the following toy program for testing the
perl PRNG,

------------
use warnings;
use constant WANT => 5;

my ($got, $needed);

do {
++$needed;
++$got if int(rand(100)) >= 89;
} while ($got < WANT);

print("needed $needed\n");
------------

there's a (pseudo-)random chance that this will print a (pseudo-)random
number of warnings in addition to the actual output. What's that
supposed to be so good for that it would excuse any of the possible
contortions which could be used to hack around that?

What's the precise logic behind something like this:

[rw@sable]/tmp#perl -we '$c = $c + 1; ++$d;'
Name "main::d" used only once: possible typo at -e line 1.
Use of uninitialized value $c in addition (+) at -e line 1.

"It is fine to use $c because 'the more, the merrier' but not as operand
in an addition whose value is assigned back to $c, however, while using
a single $d sure seems fishy, performing the exact same operation using
a traditional, syntactical shortcut on that is perfectly ok"?
 
C

Charles DeRykus

Charles DeRykus said:
If someone knows it's "useless code", I will wager he/she knows well
the dark kingdom of "uninitialized value". (if not, then some
lessons need to be experienced and having been so, you will not want
to comment on such things ever again :)

Which "dark kingdom"? Assuming the following toy program for testing the
perl PRNG,

... ]

What's the precise logic behind something like this:

[rw@sable]/tmp#perl -we '$c = $c + 1; ++$d;'
Name "main::d" used only once: possible typo at -e line 1.
Use of uninitialized value $c in addition (+) at -e line 1.

"It is fine to use $c because 'the more, the merrier' but not as operand
in an addition whose value is assigned back to $c, however, while using
a single $d sure seems fishy, performing the exact same operation using
a traditional, syntactical shortcut on that is perfectly ok"?

Yes, it sorta makes "sense". The ++$d draws an lvalue exemption from
"uninitialized value" but then perl agrees a single mention is fishy.
However $c=$c+1 is too complex to equate to a simple preinc so it draws
the "uninitialized" warning would be my guess.
 
R

Rainer Weikusat

Charles DeRykus said:
On 9/20/2013 7:09 AM, Rainer Weikusat wrote:
[...]
What's the precise logic behind something like this:

[rw@sable]/tmp#perl -we '$c = $c + 1; ++$d;'
Name "main::d" used only once: possible typo at -e line 1.
Use of uninitialized value $c in addition (+) at -e line 1.

"It is fine to use $c because 'the more, the merrier' but not as operand
in an addition whose value is assigned back to $c, however, while using
a single $d sure seems fishy, performing the exact same operation using
a traditional, syntactical shortcut on that is perfectly ok"?

Yes, it sorta makes "sense". The ++$d draws an lvalue exemption from
"uninitialized value" but then perl agrees a single mention is
fishy. However $c=$c+1 is too complex to equate to a simple preinc so
it draws the "uninitialized" warning would be my guess.

"Code does $something" doesn't imply "$something is sensible". Wrt to
'uninitialized values' in expressions, there are basically three
choices:

- compile-time error
- runtime error
- define a meaning for that

'Define a meaning for that but then emit an optional runtime warning
except in case of the following expressions ..., ..., ...' [perfectly
arbitrary collection of stuff which ocurred in code written by the
person who designed/ implemented the warning] is IMHO just a bizarre
inconsistency, sort-of "do a little bit of everything", that is,
don't really do anything, but muddy the waters enough to hide that.
 

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

Forum statistics

Threads
473,744
Messages
2,569,483
Members
44,901
Latest member
Noble71S45

Latest Threads

Top