in reply to I want to operate on some values in a hash

I'm averse to for ()
Why? The intended meaning of map is to create a new list from an old one. So modifying a set of values with map (rather than create a new set) is considered bad practice. You might do @h{@k} = map { stuff($_) } @h{@k} if you really want to avoid a for loop, or s/stuff/other/ for @h{@k}; if it's having multiple lines that bothers you.

Edit: when I say that modifying a set of values with map is considered bad practice, I'm talking about the inplace modification of elements, as in map { $_ += 2 } @numbers;, (or the dreaded "map in void context"). @h{@k} = map { stuff($_) } @h{@k} isn't as bad, as it actually builds a temporary new list, before overwriting the values in the hash. It's just neither the most straightforward way, nor the usual way. But as long as there's no inplace editing, that's fine IMHO.

Replies are listed 'Best First'.
Re^2: I want to operate on some values in a hash
by pwagyi (Monk) on Jan 05, 2018 at 01:49 UTC
    I agree with Eily that using map for in-place modification is bad practice. I think you could just use filter & map to produce newly generated hash.
    my %modified_hash = map { $_ => f($hash{$_}) grep { condition_on_key($_) } keys(%hash);
    Edit: s/list/hash/
Re^2: I want to operate on some values in a hash
by misterperl (Friar) on Jan 04, 2018 at 16:26 UTC
    Eily: " modifying a set of values with map (rather than create a new set) is considered bad practice" I'd actually never read that, can you elaborate? I often do that with great success. But if there are side-effects or dangers I'm not aware of I'd like to know that.. Thanks

      I suppose you wrote that before I edited my message?

      Honestly I can't remember seeing the map in void context for a while, except when I mention that people keep bringing up the subject myself (but I did see it often in my earlier readings on perlmonks), make of that what you will.

      One reason for the discussion is that map is supposed to build a new list, and not using that output is a waste of resources. But even if map wasn't smart about its context, it's perl, you're supposed to ignore performance issues most of the time and focus on getting things done. The other issue is when you use the aliasing mechanism, ie the fact that modifying $_ will modify the input. Since ; map { $_ += 2 } @numbers; and ; $_ += 2 for @numbers; do exactly the same thing, it's clearer if you use the version that's not supposed to create a separate output. Best reason to use the second version is that you won't get told that there's a better way to do it when you post it on perlmonks :D

      NB: even without using the aliasing mechanism: ; map { $h{$_}++} @keys; may be better written as ; $h{$_}++ for @keys;, because map does something from the input, while for does something with the input. Nitpicking at its finest :)

      It's strictly verboten since the birth of the cool AKA hour zero or so. May be one of our founders imposed this but no one remembers who it really was. But remember: Things that are verboten - like perl -E 'map {++$_; say;} 0..9' - give the real kick ;-) For a more serious debate please see map vs for\foreach..

      Best regards, Karl

      «The Crux of the Biscuit is the Apostrophe»

      perl -MCrypt::CBC -E 'say Crypt::CBC->new(-key=>'kgb',-cipher=>"Blowfish")->decrypt_hex($ENV{KARL});'Help