Lennotoecom has asked for the wisdom of the Perl Monks concerning the following question:

$h{'11c'} = 'C'; $h{'b'} = 'B'; $h{'e22'} = 'E'; $h{'aaaaa'} = 'AAAA'; for (keys %h){ $a = \$h{$_} and $b = $_ if $a < \$h{$_}; } print "$b\n";
What do you think? Besides obvious.

Replies are listed 'Best First'.
Re: the last added element of a hash
by Athanasius (Archbishop) on Jul 31, 2014 at 09:24 UTC

    Hello Lennotoecom,

    I would re-write this idea as follows:

    #! perl use strict; use warnings; use List::Util 'max'; my %h = ( '11c' => 'C', b => 'B', e22 => 'E', aaaaa => 'AAAA', ); if (%h) { my $last = max map { \$_ } values %h; printf "The last element added to the hash was %s\n", $$last; } else { print "No elements have been added to the hash\n"; }

    This gives the same result, but:

    • compiles under use strict;
    • runs without warnings under use warnings; and
    • handles the case where the hash is empty.

    This script’s output (like the title of this node) is still somewhat misleading, however, as “last element added” really means “last element added of those still remaining in the hash.” For example, if you add elements X, Y, and Z, and then delete element Z, this script will output Y as the “last element added,” which isn’t strictly correct.

    But the real problem with this whole strategy is that it relies on an implementation detail of the perl interpreter; namely, that it always assigns new hash values to memory addresses above those of previously-assigned values. Is this guaranteed to be the case? Will it always be true of perl implementations in the future? I don’t know, and for that reason I would advise against this approach until and unless it can be proven to be valid now and also future-proof.

    Hope that helps,

    Athanasius <°(((><contra mundum Iustus alius egestas vitae, eros Piratica,

      > always assigns new hash values to memory addresses above those of previously-assigned values. Is this guaranteed to be the case? 

      No, as soon as an address is freed again it might be reused.

      Just try to delete an entry and create new ones ...:)

      Cheers Rolf

      (addicted to the Perl Programming Language and ☆☆☆☆ :)

      update

      Not a meditation and poorly worded!

      moved to SOPW.

        In fact this smell like things you never have to attempt..
        good point LanX!

        But you Lennotoecom, what do you think about? your meditation is so poor in words...

        Can i add: when you play with memory's addresses in Perl you are always going in a wrong direction.

        L*
        There are no rules, there are no thumbs..
        Reinvent the wheel, then learn The Wheel; may be one day you reinvent one of THE WHEELS.
      A reply falls below the community's threshold of quality. You may see it by logging in.
Re: the last added element of a hash
by AppleFritter (Vicar) on Jul 31, 2014 at 09:07 UTC
    Cute, but don't rely on this. If you want an ordered hash, use e.g. Tie::IxHash.
Re: the last added element of a hash
by Jenda (Abbot) on Jul 31, 2014 at 14:28 UTC
    $h{'11c'} = 'C'; $h{'b'} = 'B'; $h{'e22'} = 'E'; $h{'aaaaa'} = 'AAAA'; for (keys %h){ $a = \$h{$_} and $b = $_ if $a < \$h{$_}; } print "$b\n"; { my $str = "bogus" x 10000; $h{foo} = 'F'; } $h{bar} = 'B'; for (keys %h){ $a = \$h{$_} and $b = $_ if $a < \$h{$_}; } print "$b\n";

    I get "foo" like this and "bar" if I change the 10000 to 1000. The numbers may be different for you, but as soon as things happen between the additions, you are not guaranteed to get the last. Even just computing the values for the hash could cause changes to the result.

    Jenda
    Enoch was right!
    Enjoy the last years of Rome.

Re: the last added element of a hash
by parv (Parson) on Jul 31, 2014 at 08:47 UTC

    Rewrite the loop body for the obvious reasons, of course.