in reply to Curious: are anon-hashes in random order?

Hi perl-diddler,

Isn't the stuff in brackets an anonymous hash? Isn't the ordering of hashes strictly not guaranteed by default?

Yes and yes.

So how could that work, since the numbers and the labels in the hash, it would seem, should end up in a random order?

Note that "random order" does not mean this:

use List::Util qw/shuffle/; my @order = shuffle qw/ continue 0 next 1 redo 2 last 3 /;

What it means is this:

my @keyorder = shuffle qw/ continue next redo last /;

So constant will always define four subs, which return the value associated with each key in the hash. It is equivalent to the following code; the order in which the subs are defined does not matter. (By the way, I think that defining subs with the same name as those Perl builtins is likely to cause confusion later.)

sub continue () { 0 } sub next () { 1 } sub redo () { 2 } sub last () { 3 }
I know the following would fail (because the RHS of the 'our $clist' won't be done at compile time):

Correct, but this would work:

our $clist; BEGIN { $clist = {continue=>0, next=>1, redo=>2, last=>3 } } use constant $clist;
But how is it that this seems to always work:

If I understand mem correctly, it's essentially doing the same thing as the code with the BEGIN block above. Also, remember that use Module LIST is exactly equivalent to BEGIN { require Module; Module->import( LIST ); }.

Is it that compile-time hashes are not randomized?

No, AFAIK Perl always iterates over hashes in a random order. No, you should always treat Perl hashes as being in a random order. Also, if you note the language for example in Hash overhaul, it says "the order which keys/values will be returned ... will differ from run to run". So it's not like hashes themselves are shuffled in memory, it's the order in which they are iterated over that is randomized. So this always happens at runtime, no matter where the hashes come from. Update: Struck/reworded these sentences as potentially misleading; see BrowserUk's reply below.

Hope this helps,
-- Hauke D

Replies are listed 'Best First'.
Re^2: Curious: are anon-hashes in random order?
by BrowserUk (Patriarch) on Sep 13, 2016 at 15:22 UTC
    it's not like hashes themselves are shuffled in memory, it's the order in which they are iterated over that is randomized.

    Actually, it is neither.

    The "randomisation" takes the form of picking a single random number to seed the accumulator(*) when performing the hashing calculation for storing or retrieving the keys. Ie. by randomly initialising the accumulator, the position within the array that underlies the hash implementation, into which any given key gets stored, varies from hash to hash and run to run.

    More importantly, the order in which the underlying array is iterated (first to last) when using each or keys or values is constant for all hashes and all runs -- thus very efficient. The randomisation occurs do to the addition of a (per hash, randomly chosen once) offset that gets added to all the hashing calculations and thus causes the same key to get stored in different slots for different hashes; and different slots for the same hash for different runs.

    *there was, belatedly, some attempt to add a choice of different hashing algorithms to the mix; but these proved pointless overkill and pragmatically too inefficient; and fell into immediate disuse. If they are still needlessly cluttering the codebase -- I haven't looked lately -- it is simply because no one has got around to removing them.


    With the rise and rise of 'Social' network sites: 'Computers are making people easier to use everyday'
    Examine what is said, not who speaks -- Silence betokens consent -- Love the truth but pardon error.
    "Science is about questioning the status quo. Questioning authority". I knew I was on the right track :)
    In the absence of evidence, opinion is indistinguishable from prejudice.
      *the was, belatedly, some attempt to add a choice of different hashing algorithms to the mix; but these proved pointless overkill and pragmatically too inefficient; and fell into immediate disuse. If they are still needlessly cluttering the codebase -- I haven't looked lately -- it is simply because no one has got around to removing them

      The above can be attributed to BrowserUk, and I was hoping to register the fact that I (syphilis) had given his view a ++ (and would have given even more upvotes if such were possible).
      However, when I preview my post, I find that it is being attributed to gods.
      What is going on ? (A "god" is the last fucking thing I would want to be ;-)

      Cheers,
      Rob
        However, when I preview my post, I find that it is being attributed to gods.

        It seems, though I never noticed it before, so it may be a recent change, that all previews are attributed to "gods", until you commit them.

        It makes some sense in that if you choose to abandon a preview, it will be discarded, so not connecting it to a particular account before that point might save some DB fiddling.


        With the rise and rise of 'Social' network sites: 'Computers are making people easier to use everyday'
        Examine what is said, not who speaks -- Silence betokens consent -- Love the truth but pardon error.
        "Science is about questioning the status quo. Questioning authority". I knew I was on the right track :)
        In the absence of evidence, opinion is indistinguishable from prejudice.

      Hi BrowserUk,

      I admit my knowledge of the internals of hashing is limited; thank you for the clarification!

      Regards,
      -- Hauke D

Re^2: Curious: are anon-hashes in random order? (updated)
by perl-diddler (Chaplain) on Sep 13, 2016 at 21:20 UTC
    So constant will always define four subs, which return the value associated with each key in the hash. It is equivalent to the following code; the order in which the subs are defined does not matter. (By the way, I think that defining subs with the same name as those Perl builtins is likely to cause confusion later.)
    Never has in my usage -- you have to use the constants prefixed with '&' -- while putting '&' in front of those keywords is guaranteed to cause an error. So how could it cause confusion?
    If I understand mem correctly, it's essentially doing the same thing as the code with the BEGIN block above. Also, remember that use Module LIST is exactly equivalent to BEGIN { require Module; Module->import( LIST ); }.
    Well, as mentioned elsewhere, it's a side effect of perl, not really a feature of mem -- though mem supports the side-effect in perl by guaranteeing not to throw an error for that type of usage, making it an ideal candidate for the shorter usage.

    mem's primary purpose was to allow packages that were already defined in a file to be "used" from the "in-memory" copy already parsed, rather than searching through your module path on disk, as is perl's default behavior. It allows easier inclusion of multiple "packages" in the same file -- which makes sense when the packages are related, meant to be data structures, or similar. Of course mem is only needed when you are 'use'ing the module vs. having the module function as a data structure.

    When I declare struct's in perl, it takes about 3-4 lines (sorry, Data::Vars, is _still_ in my personal library and hasn't be cpanned yet -- stable, but publishing it would require alot of added tests and docs to be written), but using it is fairly simple:

    > tperl # an alias { package foo; use Data::Vars [qw(a b c) ], {c=>sub{ {} }}; #c gets a default 1} package main; my $p = foo->new({a=>1}); # a passed as arg $p->b = [qw(one two three)]; # b assigned to at runtime P "p=%s", $p; # and result ' p=foo{a=>1, b=>["one", "two", "three"], c=>{}}
    The primary purpose behind most of my modules is to simplify, save space and unnecessary typing. FWIW, 'c' is initialized with a sub around the hash so the same hash isn't assigned to each new copy of the data-structure.
      > use the constants prefixed with '&'

      But then it's not parsed as a constant, i.e. it isn't inlined:

      $ perl -MO=Deparse -e 'use constant c => 42; print c; print &c;' sub c () { 42 } use constant ('c', 42); print 42; print &c; -e syntax OK
      ($q=q:Sq=~/;[c](.)(.)/;chr(-||-|5+lengthSq)`"S|oS2"`map{chr |+ord }map{substrSq`S_+|`|}3E|-|`7**2-3:)=~y+S|`+$1,++print+eval$q,q,a,

      Hi perl-diddler,

      So how could it cause confusion?

      You as the author may be able to keep track of the keywords vs. subs, and Perl may be able to resolve the ambiguity most of the time, but it's not too difficult to accidentally cross the line where Perl may pick the wrong definition (for example, there's the warning "Ambiguous call resolved as CORE::continue(), qualify as such or use & at ..."). Also, another reader of your code (including a future maintainer - or even your future self) could easily become confused between next and &next, etc.

      It's just one of those cases where as long as you know what you are doing and your script isn't intended for distribution then it's probably fine; but if you do intend the code for a wider audience then I was just pointing out that there are some good rules of thumb / conventions, such as not to define subs with the same name as Perl builtins unless you intend to replace them, and that constant names are typically uppercased.

      Regards,
      -- Hauke D

        Well, in this case, the code had been in a loop. The loop got large, so moved contents out, but then the loop control words no longer worked. In this case, the loop control words made it clear the derived sub, where the code in the main loop would go next. I used those constants (and have done similar in the past) for exactly those reasons -- even though the loop contents were no longer "inline", due to the use of such constants to indicate what they did in their previous loop the code was actually easier to understand -- more clear.

        If I had come up with a new or different set of constants, I don't think it would have been as clear. As for constants being upcased? That's so 80's. :-) Seriously -- all caps hurt my eyes and fingers typing -- I'll usually capitalize something, but there are many cases where doing so hurts perception and understanding.

        An example would be several math constants (displaying these on pm in code blocks, is bugged, so you'll have to use your imagination a bit: ( But the 3 chars are Φ (Phi), ɸ (phi) and π (pi) ).

        sub Phi () { .5 * (5.**.5 - 1) } sub Φ () { goto &Phi } sub phi () { .5 * (1. + 5.**.5) } sub ɸ () { goto &phi } sub pi () { 4 * atan2(1, 1) } sub π () { goto &pi }
        If you upper-cased these, how would you tell Phi from phi. In the greek names (on the right which display as characters on modern systems), they are also the upper and lower case version of the greek phi. Pi, uses a lower case 'pi' just as it is in the english text version.

        Anyway, it's all about context... ;-)...