I found the code below today while researching a new patch to PM. I thought it made a good example of a Perl Idiom. I find that I'm so used to "the Perl way" that code like this becomes extremely hard to read. I had to consciously think what this code did. (I've removed the usage doc to make it even harder :-)

sub getRef { my $this = shift @_; for (my $i = 0; $i < @_; $i++) { unless (ref ($_[$i])) { $_[$i] = $this->getNodeById($_[$i]) if($_[$i]); } } ref $_[0]; }

And I think its because I probably would have written it like this:

sub getRef { my $self=shift; for (@_) { next if ref $_ or !$_; $_=$self->getNodeById($_); } ref shift; }

:-)

PS, I know it could be smaller, but this is how I would write for work for instance. Although I probably wouldnt write such code in the first place, but thats another story...


---
demerphq

    First they ignore you, then they laugh at you, then they fight you, then you win.
    -- Gandhi


• Update:  
Some good catches of typos by gmax,vsarkiss and roju.


Replies are listed 'Best First'.
Re: The trouble with Perl Idiom
by diotalevi (Canon) on Aug 26, 2004 at 19:29 UTC

    Say, what's the deal with transforming every element of @_ after the first but then returning the second element? You never get constant values as parameters?

    Anyhow, if you write code as list-processing stuff with nice indentation you get something that even looks Pythony. What could be prettier than that?

    sub getRef { shift; # !!! $this is a global return map ref $this->getNodeById( $_ ), grep $_ && not ref, @_; }
      Pretty :)
      sub getRef { my $self = shift; $_ and ref $_ and $_ = $self->getNodeById($_) for @_; ref shift; }

      MJD says "you can't just make shit up and expect the computer to know what you mean, retardo!"
      I run a Win32 PPM repository for perl 5.6.x and 5.8.x -- I take requests (README).
      ** The third rule of perl club is a statement of fact: pod is sexy.

      I think its so you can say stuff like

      if (getRef($node)) { ... }

      and be sure that $node is now indeed a PM $NODE hashref. As I said, this isn't a technique I would probably employ. I'm sure the Everything folks have their reasons, but to me its an odd routine in the first place.

      Oh, i should say, that for a lot of PM methods there are functional wrappers, so where the normal $obj->getRef($node) would be written in htmlcode it would be as a plain getRef() call.


      ---
      demerphq

        First they ignore you, then they laugh at you, then they fight you, then you win.
        -- Gandhi


        I'm sure the Everything folks have their reasons

        Let me assure you, they're not good ones and that code wouldn't look the same today.

Re: The trouble with Perl Idiom
by Juerd (Abbot) on Aug 27, 2004 at 05:43 UTC

    Why does your Perl way involve cramming everything together, while your C way has whitespace around operators like =? And why does your Perl way have strangeCaps? Iteration over @_ to just use its first element? Why are the curlies different?

    Because there is not one Perl way, and certainly no "the" Perl way. There is more than one (Perl) way to do it.

    My Perl way may be someone else's Javascript/PHP/Whatever way, and vice versa. The style you choose to program in isn't the only one.

    Juerd # { site => 'juerd.nl', plp_site => 'plp.juerd.nl', do_not_use => 'spamtrap' }

      Why does your Perl way involve cramming everything together, while your C way has whitespace around operators like =?

      I dont tend to put a lot of whitespace in my subs. The "C way" wasnt written by me so I can't explain.

      And why does your Perl way have strangeCaps?

      Both have camelHumpIdentifiers. Its part of the original PM convention. Personally I hate it and would prefer perl_style_identifiers instead.

      Iteration over @_ to just use its first element?

      You didnt read the code very closely then, iteration over @_ occurs in both and is intended to convert all node_id's in the argument list into $NODE hashrefs. The fact that a return is generated from the first non $self argument is just an added utility. Imagine you might say:

      my @ids=(1,2,3,4); getRef(@ids); printLog($_->{title}) for @ids;

      Why are the curlies different?

      I use cuddled else style curlies. Obviously the author of that nodes doesnt.

      Im not really sure what your point here is. Sure my way isnt the only one, sure there are other ways that are still "the perl way". But clearly the first isnt one of them, or at least wouldnt normally be perceived as such.

      Anyway, I think you totally missed the point. The point was that using proper Perl idiom you wouldnt go through all the extra work the original does to do what it is meant to do. And that for someone used to the idiom even realizing that the two code snippets are identical takes a bit of thinking. Or it did me anyway.


      ---
      demerphq

        First they ignore you, then they laugh at you, then they fight you, then you win.
        -- Gandhi


        Im not really sure what your point here is. Sure my way isnt the only one, sure there are other ways that are still "the perl way". But clearly the first isnt one of them, or at least wouldnt normally be perceived as such.

        I tried to point out that everyone's style is different and that the first snippet isn't any less a Perl way than the second. It's a different way.

        Most Perl that I encounter in the wild is like your first snippet. Note that most Perl coders do not live in "the community" and never see the neat idioms that we could not happily live without.

        Juerd # { site => 'juerd.nl', plp_site => 'plp.juerd.nl', do_not_use => 'spamtrap' }

Re: The trouble with Perl Idom
by bluto (Curate) on Aug 26, 2004 at 19:34 UTC
    Let me guess: an old C programmer wrote this code, using C idioms? Yeah, I used to do that kind of stuff too when I first learned Perl. C does strange things to one's mind... :-)
Re: The trouble with Perl Idiom
by Aristotle (Chancellor) on Aug 29, 2004 at 19:59 UTC

    That reads awkwardly, I find. This is how I'd write it:

    sub getRef { my $self = shift; $_ = $self->getNodeById( $_ ) for grep { $_ and not ref } @_; return ref $_[0]; }

    It maps more closely to the way I think of the problem. You can almost read it out in natural language: "filter it through $self->getNodeById() for every element that is true and not a reference".

    Makeshifts last the longest.

      I almost never chain grep together with another looping structure. I see no reason to iterate lists twice.


      ---
      demerphq

        First they ignore you, then they laugh at you, then they fight you, then you win.
        -- Gandhi


        That is an implementation detail. :-)

        Remember, code is written primarily for programmers to read and only incidentally for a machine to execute. Did you profile this and found it to be a problem?

        NB: I quarreled with the thought of adding a note to the effect that this construct loops twice on my previous node, but decided against it. The typical data set in this function would consist of one element, or of less than 10 elements in most other cases. Musing about its efficiency therefore seems like a rather pointless excercise.

        Makeshifts last the longest.