borisz has asked for the wisdom of the Perl Monks concerning the following question:
Hi, I typed:
perl -e '%h = ( q => 2, w => 2 ); print reverse %h = reverse %h'
and wonder why I get three values back 'w22' I expect 'q2' or 'w2' at perls option.
More testing shows even more wired results.
In the example below, I expect %x reversed in %h but it is not. There was not even a 'a' => 2 pair in the original %h.
perl -MData::Dumper -le '%h = (1 => 2, a=>"b", c => 2); %h = reverse (
+ %x = reverse %h); print Dumper({x => \%x, h =>\%h});'
__OUTPUT__
$VAR1 = {
'x' => {
'b' => 'a',
'2' => 'c'
},
'h' => {
'a' => 2,
'c' => 2
}
};
Perl 5.8.4 cofuses me even more
perl5.8.4 -MData::Dumper -le '%h = (1 => 2, a=>"b", c => 2); %h = reve
+rse ( %x = reverse %h); print Dumper({x => \%x, h =>\%h});'
__OUTPUT__
$VAR1 = {
'x' => {
'b' => 'a',
'2' => 'c'
},
'h' => {
'' => 2
}
};
can you explain this behavior please?
UPDATE: I really expect to lose the dupes. My point is that I expect that %h is a reverse of %x. But it is not for me, tested on
Mac OSX and Linux. So I really wonder that you get different output.
Re: whats wrong reverse %x = reverse %h?
by blokhead (Monsignor) on Sep 28, 2004 at 16:52 UTC
|
use Data::Dumper;
my %h = (1 => 2, a => "b", c => 2);
print Dumper [ my %x = reverse %h ];
I get a Bizarre copy of ARRAY in anonlist (perl v5.8.3). Same if I try to do
print Dumper { my %x = reverse %h };
I have no idea what (my %x = reverse %h) evaluates to in list context, but whatever it is, Perl doesn't like it. The fact it doesn't die with the Bizarre copy error when using that expression as function arguments might be a bug...
Anyway, back to your original question, if you split the two reverses into two statements like
%h = reverse do { my %q = reverse %h; %q };
you'll get what you expect.
| [reply] [d/l] [select] |
Re: whats wrong reverse %x = reverse %h?
by waswas-fng (Curate) on Sep 28, 2004 at 16:48 UTC
|
perl -MO=Deparse -MData::Dumper -le '%h = (1 => 2, a=>"b", c => 2); %h
+ = reverse ( %x = reverse %h); print Dumper({x => \%x, h =>\%h});'
BEGIN { $/ = "\n"; $\ = "\n"; }
use Data::Dumper;
(%h) = (1, 2, 'a', 'b', 'c', 2);
(%h) = reverse((%x) = reverse(%h));
print Dumper({'x', \%x, 'h', \%h});
-e syntax OK
as stated above your reverse/reverse of the hash is causing you to lose dup keys...
| [reply] [d/l] |
|
Dont get me wrong, I really expect to lose the dup keys, but my output lose much more then the dupes.
| [reply] |
Re: whats wrong reverse %x = reverse %h?
by Zaxo (Archbishop) on Sep 28, 2004 at 16:40 UTC
|
When you reverse the list you get from a hash, keys and values are exchanged. Making a hash from the reversed list, if two values are the same, only one of the previous keys will survive as a value.
Added - I get 'w2' running your first example, but get the same as you with the second. There may be some optimization with aliases going wrong. I don't see that the construction is supposed to be undefined.
| [reply] |
|
Thats what I expect, but none of the examples show this behavior.
the expected results from the first is for %h
{ 2 => 1, b=> 'a' } or { 2 => 'c', b=> 'a' }
but the result is
{ a => 2, b => 2}
even more unexpeted results from perl 5.8.4 where I get
{ '' => '2' }
| [reply] [d/l] [select] |
Re: whats wrong reverse %x = reverse %h?
by melora (Scribe) on Sep 28, 2004 at 21:19 UTC
|
I did a little playing with this, to try to learn something.
%h = (1 => 2, a=>"b", c => 2);
%h = reverse (%x = reverse %h);
foreach my $n (keys %h) {
print "$n $h{$n}\n";
}
Yeah, I know. Anyway, here's what I get:
2
1 2
a b
As if a duplicate element were eliminated by making the key null. But if I do
%h = (1 => 2, a=>"b", c => 2);
%x = reverse %h;
%h = reverse %x;
foreach my $n (keys %h) {
print "$n $h{$n}\n";
}
I get
1 2
a b
which is what I'd expect. Now, here's yet another thing: if I create another duplicate, d => 2 (at the end of the list), I still get the same end result; that duplicate is eliminated. In fact, in the first bit of code, I still get three lines of output. If there are duplicates, it doesn't seem to be guaranteed which one is eliminated by the reverse. I just looked at reverse in my Camel book and it doesn't mention anything about duplicates, so I suspect the order can't be relied upon. Typical for a hash. | [reply] [d/l] [select] |
Re: whats wrong reverse %x = reverse %h?
by jZed (Prior) on Sep 28, 2004 at 16:44 UTC
|
I get 'w2' (no second 2) using perl 5.8.3. on winXP. | [reply] |
|
Same for me on perl, v5.8.4 built for i686-linux.
"There is no shame in being self-taught, only in not trying to learn in the first place." -- Atrus, Myst: The Book of D'ni.
| [reply] |
Re: whats wrong reverse %x = reverse %h?
by Keystroke (Scribe) on Sep 29, 2004 at 14:55 UTC
|
Maybe it has something to do with print being on the same
line?
Weird.
% perl -e '%h = (q => 1, w => 2, x => 0, y => 2);\
print join ",", reverse %h = reverse %h;'
w,2,x,0,,2,q,21
% perl -e '%h = (q => 1, w => 2, x => 0, y => 2);\
%h = reverse %h; print join ",", reverse %h;'
w,2,x,0,q,21
| [reply] [d/l] |
|
|