Beefy Boxes and Bandwidth Generously Provided by pair Networks
Syntactic Confectionery Delight
 
PerlMonks  

Re^2: using ref to hash of hash effectively

by eyepopslikeamosquito (Archbishop)
on Dec 27, 2020 at 08:58 UTC ( [id://11125781]=note: print w/replies, xml ) Need Help??


in reply to Re: using ref to hash of hash effectively
in thread using ref to hash of hash effectively

Though it's nice to show different ways to do it, I feel obliged to point out that many folks disapprove of using map in void context.

Though map in void context no longer suffers the huge performance penalty it once did, some still consider it poor style (see, for example, the performance-related discussion in this old thread).

I personally applaud the simple stylistic advice summary given in Effective Perl Programming in the item "Use foreach, map and grep as appropriate", namely:

  • Use foreach to iterate read-only over each element of a list
  • Use map to create a list based on the contents of another list
  • Use foreach to modify elements of a list
  • Use grep to select elements in a list
because I find the code clearer and easier to maintain if everyone in my team follows those four simple rules.

Note that Perl::Critic provides a ProhibitVoidMap policy to allow the code police to prohibit using map in void context.

Replies are listed 'Best First'.
Re^3: using ref to hash of hash effectively
by alexander_lunev (Pilgrim) on Dec 27, 2020 at 11:40 UTC

    Well, yes, there are some folks, that disapprove using our beloved language in some way that they think is wrong. But this is an aesthetical dispute, not technical. Some folks like it one way, other folks like it another way - and they do so they like, and all they do is beautiful (at least to themselves), and our main principle - multiple ways of doing one thing - flourishes.

    And in a spiritual matter, it is a god's blessing that recipes from no-map-in-void-context part of folks and recipes from the other folks has been given. In a dark times of which I think no need to mention, every single group, even one that think of using-map-in-void-context as of heresy, comes to help seeking wisdom in our monastery.

    And thank you for pointing out that our beloved monastery is not a dogmatic place. Yes, there are different monks that chant for gloriness with different means and using different techniques, and all as one are welcoming and kind to strangers - and to themselves. Such fellowship is a true blessing.

      I hope that we all can agree that when it comes to style issues, we should each be consistent. When one of these issues arises, we should form a standard which we are comfortable with and always use it.

      In this case, I like the standard suggested by eyepopslikeamosquito. For my own use, I have added another rule. "No map or grep block should produce any side effects."

      Bill

        With all my respect, I can't agree with you about coding standards while we lending a helping hand to person in search of wisdom. I'll try to explain it more thoroughly. Here's a quote from Wikipedia:

        Coding conventions are only applicable to the human maintainers and peer reviewers of a software project. Conventions may be formalized in a documented set of rules that an entire team or company follows, or may be as informal as the habitual coding practices of an individual.

        I will not dispute about having coding conventions and standards in a team or in a company. It is perfectly clear that coding style should be consistent - in a team! But we're talking here about ideas, about ways to solve some problem. Everyone could write in a style that in his opinion is right, I don't see problems here. But to say "We in our team using this coding standard, and so should you" - do you think it's relevant?

        Once again - it's aesthetical dispute, not technical. It's good to know about worries of context when using map, but there are no technical reasons to resolve this question to one or another side of dispute. And there is a humanitarian side of this question: should we give people freedom with full undestanding that freedom can also lead to some bad things, or should we limit the freedom to protect people? I'm for the first part.

        I don't want to wage a holy war here. You think map in void context is bad? I'm ok with that. You can use it how you want it. What really matters is - hear this - exchange of ideas. Author of original post wrote to me that he found helpful idea of using map with precalculated @sum_fields from my example - and I'm happy with that. We're not all geniuses here, and sometimes a simple advice can save a person's time - the most valuable resource in human life. Aren't we all should try to help each other - for this purpose, for time saving? Think of it: in the end, at the death's door, what would be more precious for you: that you promoted coding standard that you think is right, or that you helped someone to save minutes of his life?

        And yes, when we're coding as a team, coding conventios is perfectly legal.

      In terms of aesthetics, my feeling is "each to his own". I used to use map in void context. I have no problem reading code like that. I no longer use it, but for completely different reasons (see below).

      The performance hit was resolved in 5.8.1 (see "perl581delta: Miscellaneous Enhancements"). If you're coding to 5.8.0 or earlier, you should avoid map in void context; otherwise, the performance issue is moot.

      Quite a few years ago, I benchmarked map against for. I was surprised at how much faster for was. That's the reason I would now choose

      for (keys %{ $weapons_ref }) { ... }

      over

      map { ... } keys %{ $weapons_ref };

      See Benchmark and run your own tests if you want.

      — Ken

        Thank you for this. I've done this benchmark:

        use strict; use Benchmark qw(:all); my $weapons_ref = { dagger => { cost => 8, damage => 4, armor => 0 }, shortsword => { cost => 10, damage => 5, armor => 0 }, warhammer => { cost => 25, damage => 6, armor => 0 }, longsword => { cost => 40, damage => 7, armor => 0 }, greataxe => { cost => 74, damage => 8, armor => 0 }, }; my @sum_fields = qw/cost damage armor/; my $count; cmpthese($count, { 'MapSub' => sub { my $sum_result; map { my $name = $_; map { $sum_result->{$_} += $weapons_ref->{$name}->{$_} } @sum_ +fields } keys %{ $weapons_ref }; }, 'ForSub' => sub { my $sum_result; foreach my $name (keys %{ $weapons_ref }) { foreach my $field (@sum_fields) { $sum_result->{$field} += $weapons_ref->{$name}->{$field}; } } }, });

        And here's result:

        Rate MapSub ForSub MapSub 197098/s -- -33% ForSub 294627/s 49% --

        map is a bit slower, yes, but not critical. Anyway, thank you again, I will remember this if have to do code optimization.

Log In?
Username:
Password:

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

How do I use this?Last hourOther CB clients
Other Users?
Others admiring the Monastery: (7)
As of 2024-04-19 06:58 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found