sundialsvc4 has asked for the wisdom of the Perl Monks concerning the following question:
Idly curious ... Why the difference?
$ perl -e 'my %keys={A=>"b"};my ($a,$b); while (($a,$b)=each %keys) {
+print "$a $b\n"; }'
HASH(0x100804ed0)
vs.
$ perl -e 'my $keys={A=>"b"};my ($a,$b); while (($a,$b)=each %$keys) {
+ print "$a $b\n"; }'
A b
The second one-liner, which declares a hashref, produces the result that I expect. The first one, with a hash, doesn’t. ($b is undefined.)
Re: Why? (each...)
by toolic (Bishop) on May 11, 2011 at 13:35 UTC
|
$ perl -Mdiagnostics -e 'my %keys={A=>"b"};my ($a,$b); while (($a,$b)=
+each %keys) { print "$a $b\n"; }'
Reference found where even-sized list expected at -e line 1 (#1)
(W misc) You gave a single reference where Perl was expecting a li
+st
with an even number of elements (for assignment to a hash). This u
+sually
means that you used the anon hash constructor when you meant to us
+e
parens. In any case, a hash requires key/value pairs.
%hash = { one => 1, two => 2, }; # WRONG
%hash = [ qw/ an anon array / ]; # WRONG
%hash = ( one => 1, two => 2, ); # right
%hash = qw( one 1 two 2 ); # also fine
Use of uninitialized value in concatenation (.) or string at -e line 1
+ (#2)
(W uninitialized) An undefined value was used as if it were alread
+y
defined. It was interpreted as a "" or a 0, but maybe it was a mi
+stake.
To suppress this warning assign a defined value to your variables.
To help you figure out what was undefined, perl tells you what ope
+ration
you used the undefined value in. Note, however, that perl optimiz
+es your
program and the operation displayed in the warning may not necessa
+rily
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.
HASH(0x60b220)
| [reply] [d/l] |
Re: Why? (each...)
by Corion (Patriarch) on May 11, 2011 at 13:37 UTC
|
Because your first hash only contains one key, HASH(0x100804ed0). Had you used warnings, Perl would have told you so:
>perl -we "my %keys={A=>'b'};my ($a,$b); while (($a,$b)=each %keys) {
+print qq($a $b\n); }"
Reference found where even-sized list expected at -e line 1.
...
A hash is assigned a list, not a hash reference. | [reply] [d/l] [select] |
Re: Why? (each...)
by LanX (Saint) on May 11, 2011 at 13:36 UTC
|
my %keys={A=>"b"} should be my %keys=(A=>"b")
| [reply] [d/l] [select] |
Re: Why? (each...)
by ikegami (Patriarch) on May 11, 2011 at 15:48 UTC
|
{ A => "b" }
creates a hash and returns a reference to it, like
do { my %anon = ( A => "b" ); \%anon }
So you are doing
my %anon = ( A => "b" );
my %keys = \%anon;
When you assign to a hash, it expects a list of key-value pairs. You just provide one item, so it's use as a key and undef is used as a value. (This would have given you a warning if you had them on!)
So you are doing
warn("Odd number of elements in hash assignment");
my %anon = ( A => "b" );
my %keys = ( \%anon => undef );
To return the contents of a referenced hash, you need to dereference it.
my %keys = %{ { A => "b" } };
But there's no reason to construct the anonymous hash at al. You could just use
my %keys = ( A => "b" );
| [reply] [d/l] [select] |
Re: Why? (each...)
by sundialsvc4 (Abbot) on May 11, 2011 at 20:29 UTC
|
Most curious. Now... not being entirely a babe in the woods about such things, I did run this with use strict; use warnings; (on Perl 5.10.0; OS/X Snow Leopard), albeit not with use diagnostics;, and it didn’t say anything.
Truth be known, and after all these years, I still am fuzzy about the difference between “square brackets,” “braces,” and “parentheses.” If you know what I mean. (I presume that, if I asked for a show of hands right now, I would not be out here by myself...)
Oh, well. “Now, you know.™”
| |
|
$ perl -e'use warnings; my %keys={A=>"b"};'
Reference found where even-sized list expected at -e line 1.
$ perl -v
This is perl, v5.10.0 built for i686-linux
Copyr...
I still am fuzzy about the difference between “square brackets,” “braces,” and “parentheses.”
Square brackets create an array and return a reference to the array.
Curly brackets create a hash and return a reference to the hash.
Parens are like in Math. They change the order of operations.
From that, it follows that one never uses [] or {} when initialising an array or hash*, and that parenthesis aren't related to array or hash initialisation.
* — They might be used in initialising the value of an array or hash element's value, though.
Update: I added the last paragraph and the associated "*". I thought it was obvious, especially in the context of the other replies, but it might need saying.
| [reply] [d/l] [select] |
|
In the context of this discussion, wouldn't it be that parenthesis indicate a list?
Elda Taluta; Sarks Sark; Ark Arks
| [reply] |
|
|
|
|
| [reply] |
|
my %h = ($x); # List created for RHS.
my %h = $x; # List created for RHS.
my $s = ($x); # No list created for RHS.
my $s = $x; # No list created for RHS.
| [reply] [d/l] |
|
|