Beefy Boxes and Bandwidth Generously Provided by pair Networks
We don't bite newbies here... much
 
PerlMonks  

Re: Preventing unintended list expansion inside hash literals.

by LanX (Saint)
on Jan 05, 2017 at 19:24 UTC ( [id://1179025]=note: print w/replies, xml ) Need Help??


in reply to Preventing unintended list expansion inside hash literals.

Unfortunately fat comma is only going half way to be a hash separator (which is the normal use case) and there are already many use cases exploiting list context for syntactic sugar.

See for instance Re^4: Stop Using Perl and further discussion

Anyway some remarks:

  • you should have returned undef in your function, since it was never intended to be used in list context and a call in scalar context would always result to undef anyway.
  • you could have checked wantarray otherwise
  • prepending scalar is the normal idiomatic way to force scalar context (sic)
  • personally I would have chosen "" . call() to get am explicit string
  • your use of each and keys is a bit worrying, because it's globally resetting the iterator of that hash °

Cheers Rolf
(addicted to the Perl Programming Language and ☆☆☆☆ :)
Je suis Charlie!

update

°) a simple ($key) = %$hash_ref would have done the trick better

Replies are listed 'Best First'.
Re^2: Preventing unintended list expansion inside hash literals.
by vr (Curate) on Jan 06, 2017 at 19:26 UTC

    Interesting. I certainly agree with

    a simple ($key) = %$hash_ref would have done the trick better

    for clarity, terseness and, more important, lack of side effects. Unless a hash is huge:

    >perl -E "$h{$_} = $_ for 0 .. 5_000_000; say time - $^T; keys %h; say + time - $^T; $k = scalar each %h; say time - $^T; say $k" 10 10 10 852569 >perl -E "$h{$_} = $_ for 0 .. 5_000_000; say time - $^T; ($k) = %h; s +ay time - $^T; say $k" 10 176 4034296

    with equally bad effects on memory. Looks like keys in void context is harmless (performance-wise), but assignment of a hash to single-element list is not

      I did some more meditation and research...

      First of all I have to say, that I can't possibly see why one would want to store a "representative key" of a hash in another structure (like the OP did)

      Unless you want only to check if the hash is populated, then

      DB<129> scalar %empty => 0

      will do the trick without side effects ( scalar keys %empty would reset the iterator).

      Also the usual trick to copy a hash before iterating (in order to protect the iterator) is far slower than assigning to a one element list (which can't compete with each)

      DB<100> $h{$_}=$_ for 1..5e6 DB<101> $t=time; %h2=%h; print time-$t; 124 DB<102> $t=time; ($k)=%h; print time-$t; 19 DB<103> use Time::HiRes qw(time) DB<104> $t=time; ($k)=each %h; print time-$t; 7.70092010498047e-05

      BUT I have to say I'm very critical about hashes of that size, because memory consumption can easily freeze your system.¹

      Depending on use case I'd either consider using a database or a hash of hashes (of hashes ...) which is far more "swap friendly".

      Cheers Rolf
      (addicted to the Perl Programming Language and ☆☆☆☆ :)
      Je suis Charlie!

      ¹) even emptying a hash with 5e6 entries can take minutes on a netbook.

Re^2: Preventing unintended list expansion inside hash literals.
by Anonymous Monk on Jan 05, 2017 at 20:15 UTC
    bald
        Commie

Log In?
Username:
Password:

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: note [id://1179025]
help
Chatterbox?
and the web crawler heard nothing...

How do I use this?Last hourOther CB clients
Other Users?
Others chilling in the Monastery: (3)
As of 2024-04-19 21:33 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found