in reply to Re: Self-improvement and TMTOWTDI
in thread Self-improvement and TMTOWTDI

Actually, to be mildly heretical, I don't think perl offers more "extra" ways of doing things than many other languages.

Somebody _had_ to call you on this. :-)

I can think of a disturbing number of ways to iterate over the elements in an array in perl. In Pascal I can only think of a few, likewise for VB, and similarly for C/C++ (I mention this one last because I know it the least well and so might be suprised.)

Without using procedure calls I can think of the following notationally distinct means (and thats just at the moment, no doubt there are more, and i'm even ignoring the 'for' eq 'foreach' aspect that adds even more)

# 1. ... map { ... } @array; # 2. ... grep { ... } @array; # 3. for my $item (@array) { ... } # 4. ... for @array; # 5. for (my $i=0; $i<@array; $i++) { ... } # 6. my $i=0; while ($i<@array) { ... $i++ } # 7. my $i=0; while ($i<@array) { ... } continue { $i++ } # 9. my $i=0; ... , $i++ while $i<@array; # 10. my $i=0; MARK: ... $i++<@array and goto MARK; # 11. my $i=0; { ... $i++<@array and redo; } # 12. ... foreach 0..$#array; # 13. foreach (0..$#array) { ... } # 14. Blame [tye] for( pipe(IN,OUT) && do { local $,=$/; print IN @array,'' } && <OUT> ) + { ... }
That makes thirteen so far.(!) And I bet as I ride the train home a few more will come to me too. (I will update this node with any contributions that are made so please send em in. Id like to see if we can hit 20. :-)

So at least in this regard I think I would have to disagree with your claim.

Incidentally, I think that this is an interesting juxtapositioning (maybe the wrong word ill grant) of two key perl concepts. The first is "everything that is different should probably look different if at all possible", and the second is that "for everything that you can do there should be a few different looking variants available (TMTOWTDI)", which combine together nicely to match another generally held but certainly perlish imperitive which is that "code should look like it does what it does". So if we need to transform every element of a list to create a new one we use a different construct than we do if we want to apply a simple function to every element of the original, which is different from when we want to do something complicated with every element, and is also different from when we want to use the index, yada yada yada...

All in all i think this is great once you become used to it. When I see

my @array; $_++ foreach @count;
I instictively understand that the intention of the other programmer was very different to
my @array=map $_+1,@count;
which I find very useful in dealing with old code.

Cheers,

--- demerphq
my friends call me, usually because I'm late....

Replies are listed 'Best First'.
Re: Re: Re: Self-improvement and TMTOWTDI
by Tanalis (Curate) on Jan 24, 2003 at 19:36 UTC
    Just a couple of ideas ..
    my $i = 0; do { $array[$i++] .. } until $i > $#array; do { $array[$i++] .. } while $i <= $#array; JUMP: do { $array[$i++] .. } goto JUMP if $i <= $#array;
    I reckon that's 17 .. 3 to go :)

    -- Foxcub

    Update: Couple of corrections.

Re: Re: Re: Self-improvement and TMTOWTDI
by Anonymous Monk on Jan 24, 2003 at 20:08 UTC
    Some more...
    #1 while (@array) { my $elem = shift @array; ... } #2 foo(@array); ... sub foo { my $elem = shift; ... foo(@_) if @_; ... } #3 foo(@array); ... sub foo { my $elem = shift; ... &foo if @_; ... } #4 { my $elem = shift @array; ... redo if @array; }
    Duplicate these for using pop or splice rather than shift if you want. Also with your existing ones do you count for as different than foreach? Beginners do.

    I think we passed 20. :-)

Re: Re: Re: Self-improvement and TMTOWTDI
by BrowserUk (Patriarch) on Jan 25, 2003 at 01:28 UTC

    There's probably a few variations on this theme?

    @a = 1 .. 10; $i = $ENV{myI} || 10; print $a[$ENV{myI} = --$i]; do $0 if $i>0;

    Examine what is said, not who speaks.

    The 7th Rule of perl club is -- pearl clubs are easily damaged. Use a diamond club instead.

Re^3: Self-improvement and TMTOWTDI
by adrianh (Chancellor) on Jan 25, 2003 at 00:09 UTC
    Somebody _had_ to call you on this. :-)

    I knew somebody was going to slap me!

    How about Common LISP (gotta (love (those (brackets))).

    At the very least we have: count, count-if, count-if-not, every, fill, find-if, find-if-not, map, map-into, merge, mismatch, notany, notevery, nsubstitute, nsubstitute-if, nsubstitute-if-not, position, position-if, position-if-not, reduce, remove, remove-duplicates, remove-if, remove-if-not, replace, search, some, substitute, substitute-if and substitute-if-not.

    That's 30 - and I've probably missed some - different way of iterating over a sequence of elements.

    (in case anybody hasn't realised - I am not being entirely serious here :-)

      While I recognize your caveat, I cant help but think that these arent keywords. Surely most of these are compound constructs? Ie subroutines? (My lisp is minimal, but iirc lisp is a pretty minimal language itself.)

      --- demerphq
      my friends call me, usually because I'm late....

        They're all in the ANSI Common LISP standard. No libraries or extras needed.

Re: Re: Re: Self-improvement and TMTOWTDI
by CountZero (Bishop) on Jan 25, 2003 at 08:48 UTC

    It would be interesting to see whether all these different ways to iterate over the elements of an array compile more or less to the same underlying code.

    Now that would be some optimising compiler!

    CountZero

    "If you have four groups working on a compiler, you'll get a 4-pass compiler." - Conway's Law

Re: Re: Re: Self-improvement and TMTOWTDI
by jonadab (Parson) on Jan 27, 2003 at 00:23 UTC
    > Without using procedure calls I can think of
    > the following notationally distinct

    Notationally distinct is not terribly important. A number of your "different" ways are extremely minor variations. For example, 3 and 4 differ only in terms of the variable used and whether the condition is placed before or after the block; they not only do exactly the same thing, they do it in exactly the same way. Counting them as different is pedantic in the extreme; if you really think that's clever, I can easily think of a couple hundred ways to do it in line number BASIC.

    More, some of your ways to do it are simply taking more general mechanisms and applying them to a problem normally solved with a more specific type of construct. For example, using a while loop with a counter at the end of it that is not used for anything else other than to count out the iterations of the loop is something you can do in any language that has while loops, because the for loop is conceptually a special case of the while loop. Congratulations, you discovered a general principle that applies to all languages.

    Perl does have a few more than other languages, but it's not quite like you make out. Further, I'd say that these extras (like map) are not "extra" per se but are part of what makes a rich language such as Perl rich. I use Emacs lisp, and it too has some of these higher-level constructs that are essentially a specialised case of something that with a bit more work on the programmer's part could be done with standard flow control mechanisms, but the higher-level features, where appropriate, are less work to use. (And speaking of lisp, does anyone else wish Perl had an equivalent for rassq? Or does it, and I'm missing it for lack of knowing where to look?)

     -- jonadab
      Notationally distinct is not terribly important.

      You dont think so? I disagree. The notational difference reads different and thus has a different psychological impact on a maintainence programmer. But each to their own. TMTOWTDI.

      For example, 3 and 4 differ only in terms of the variable used and whether the condition is placed before or after the block; they not only do exactly the same thing, they do it in exactly the same way.

      Do tell. :-) Im afraid there is a problem however, as only one of them involves a block they dont do the same thing. And this is of course beside the above point.

      For example, using a while loop with a counter at the end of it that is not used for anything else other than to count out the iterations of the loop is something you can do in any language that has while loops, because the for loop is conceptually a special case of the while loop.

      Well I think your claim "all languages" is a little broad. And just becuase you can do this kind of equivelency in most languages doesnt mean the point is any less relevent.

      Congratulations, you discovered a general principle that applies to all languages.

      You think I am unaware that the vast majority of languages support this equivelency? Hell while we are at it why dont we lose all the non GOTO examples as conceptually GOTO maps closest to "JMP" and all of the above are ultimately implement via a CMP and conditional JMP.

      I'd say that these extras (like map) are not "extra" per se but are part of what makes a rich language such as Perl rich.

      Er. I dont see how they can not be "extras" while at the same time being part of what makes the language rich. My earlier argument was that it was exactly these extras that do make the language so rich.

      but the higher-level features, where appropriate, are less work to use.

      I think the choice of one of the solutions over the next is related to both how easy it is to write and to how closely it maps onto the semantic context of the problem at hand. But I already said that didn't I.

      --- demerphq
      my friends call me, usually because I'm late....

        > The notational difference reads different and thus has a different psychological impact

        Yes, it might do that, certainly, but for that matter so does the way you format your code in terms of whitespace and whatnot. The original poster claimed that the variety was "disturbing", but I'm not sure what's disturbing about it.

        > I'm afraid there is a problem however, as only one of them involves a block

        This is Perl; a statement is a block, yes?

        > Well I think your claim "all languages " is a little broad.

        That's why I qualified, "that has while loops". Can you name a language that has while loops but does not allow for this construct? (It is now inevitable that someone will step forward and name such a language, but it will probably be one neither of us has ever used.)

        > My earlier argument was that it was exactly these extras that do make the language so rich

        Oh, I somehow missed that, amongst the other posts. The other poster's point that the variety is disturbing is the one I disagree with really. Sorry for any confusion.

         --jonadab

      And speaking of lisp, does anyone else wish Perl had an equivalent for rassq? Or does it, and I'm missing it for lack of knowing where to look?

      No direct equivalent to rassq. Never felt the loss. I guess that's because I would usually represent an association list as a hash. Doing a reverse lookup on a hash is expensive - so I would look at some other way of representing the data.