Re: problem unless I use ".="
by demerphq (Chancellor) on May 13, 2007 at 17:40 UTC
|
FWICT you have ample explanations of why the . operator throws a warning, but it looks like nobody* has given a proper explanation of why .= does not throw a warning. And the reason is simple, it is special cased not to. Most (but not all) of the mutator style operators of the form X= (where X could be any operator symbol) are special cased not to throw warnings when used on undef lvalues. Similar rules apply to ++ and --. This is because its generally agreed that its "ok" to do stuff like $hash{somekey}++ or $hash{somekey}.=$str when $hash{somekey} doesn't have a defined value.
* well, liverpole gives an explanation but its not clear to me if the documentation he is referencing explains what he thinks it does. (UPDATE, actually im pretty sure it doesnt. :-)
---
$world=~s/war/peace/g
| [reply] [d/l] [select] |
|
demerphq & liverpole...
Thank you for clearing that up. I was unaware of such "special cased" scenarios.I appreciate your help! Also, I didn't know about the existence of the "perlop (under Assignment Operators)" reference.
Again... Thanks!
| [reply] |
Re: problem unless I use ".="
by liverpole (Monsignor) on May 13, 2007 at 14:29 UTC
|
Hi cgmd,
It's because the value of $baseball{mets} is not defined at the point you're trying to use it.
Note how the warning goes away with something like:
my $yanks = $baseball{yankees} || "";
my $mets = $baseball{mets} || "";
if ( $baseball{yankees} = $yanks.$mets ) {
foreach $_ (keys %baseball) {
print "$_ => $baseball{$_}\n";
}
}
You could also do it this way:
if ( $baseball{yankees}=($baseball{yankees} || ""). ($baseball{mets} |
+| "") ) {
foreach $_ (keys %baseball) {
print "$_ => $baseball{$_}\n";
}
}
This is all assuming, of course, that you really mean to do the assignment $baseball{yankees}=$baseball{yankees}.$mets.
If instead you are doing a comparison, you'd probably want to use eq (for string comparisons) rather than == (for numerical comparisons).
s''(q.S:$/9=(T1';s;(..)(..);$..=substr+crypt($1,$2),2,3;eg;print$..$/
| [reply] [d/l] [select] |
Re: problem unless I use ".="
by derby (Abbot) on May 13, 2007 at 14:58 UTC
|
if ( $baseball{yankees}=$baseball{yankees}.$baseball{mets} )
Assignment inside an if is unusual ..
do you mean to use assignment (=) here or do you want to compare strings? If compare, you want the string eq operator not the assignment operator (=) nor the numerical == operator.
if ( $baseball{yankees} eq $baseball{yankees}.$baseball{mets} ) {
(but that doesn't make much sense with your examples so ... )
| [reply] [d/l] [select] |
Re: problem unless I use ".="
by chargrill (Parson) on May 13, 2007 at 14:30 UTC
|
Pretty sure you'll get the warning regardless if you use $a = $a . $b vs. $a .= $b, especially given the above code.*
In your above code, $baseball{yankees} hasn't been initialized, hence the warning that you're trying to use an uninitialized value in a concatenation.
You can get more detail if you use diagnostics; at the top of your program, which yeilds:
Use of uninitialized value in concatenation (.) or string at -e line 1 (#2)
(W uninitialized) An undefined value was used as if it were already
defined. It was interpreted as a "" or a 0, but maybe it was a mistake.
To suppress this warning assign a defined value to your variables.
To help you figure out what was undefined, perl tells you what operation
you used the undefined value in. Note, however, that perl optimizes your
program and the operation displayed in the warning may not necessarily
appear literally in your program. For example, "that $foo" is
usually optimized into "that " . $foo, and the warning will refer to
the concatenation (.) operator, even though there is no . in your
program.
What are you trying to do, exactly?
If you just want to add a new key/value pair to your hash,
$baseball{yankees} = 'new york';
# OR
$baseball{yankees} = $baseball{mets};
... will suffice.
* Update: Incorrect
--chargrill
s**lil*; $*=join'',sort split q**; s;.*;grr; &&s+(.(.)).+$2$1+; $; =
qq-$_-;s,.*,ahc,;$,.=chop for split q,,,reverse;print for($,,$;,$*,$/)
| [reply] [d/l] [select] |
Re: problem unless I use ".="
by cgmd (Beadle) on May 13, 2007 at 14:48 UTC
|
I don't get the warning with:
my %baseball = (
mets => "new york",
orioles => "baltimore",
twins => "minnesota"
);
if ($baseball{yankees} .= $baseball{mets}) { # edited
foreach $_ (keys %baseball) {
print "$_ => $baseball{$_}\n";
}
}
| [reply] [d/l] |
|
Actually, you get a syntax error there, but only because you're missing the if keyword :-)
But you're correct; you don't get a warning. And that's because you're not trying to use the value of $baseball{yankees}, you're only modifying it (ie. appending to it).
Note that you do get a warning if $baseball{mets} is undefined, as in:
use strict;
use warnings;
my %baseball = (
orioles => "baltimore",
twins => "minnesota"
);
if ($baseball{yankees} .= $baseball{mets}) {
foreach $_ (keys %baseball) {
print "$_ => $baseball{$_}\n";
}
}
__END__
Use of uninitialized value in concatenation (.) or string at test.pl l
+ine 10.
s''(q.S:$/9=(T1';s;(..)(..);$..=substr+crypt($1,$2),2,3;eg;print$..$/
| [reply] [d/l] [select] |
|
Then what is being stated is that the line of code:
if ( $baseball{yankees} = $baseball{yankees} . $baseball{mets}
is not identical to:
if ($baseball{yankees} .= $baseball{mets})
Does this refute the original premise that:
$a=$a <operator> $b; is same as $a <operator> = $b; (Taken from "Beginning Perl" by Lee & Cozens)? | [reply] [d/l] [select] |
|
|