in reply to pluralization

Interesting, for sure.  I've always favored the pithier version of:
for my $count (0..2) { my $s = (1 == $count)? "": "s"; print "$count iteration$s so far...\n"; }
Of course, it's gotta be tweaked under certain circumstances:
for my $cheese_eaters (0..2) { my $noun = (1 == $count)? "mouse": "mice"; print "$cheese_eaters $noun so far...\n"; }
By the way, the (<constant> == $count) is a habit I picked up from a company which had some good ideas about coding guidelines.  (It was for C, but applies to Perl as well).  The idea is that you can never accidentally write '=' instead of '==' because the compiler will detect an attempt to assign to a constant and forbid it outright.

Replies are listed 'Best First'.
Rere: pluralization
by Vynce (Friar) on Sep 09, 2005 at 01:57 UTC

    i think the x notation should theoretically be faster, because there is no branch -- just a repeat some (possibly zero) number of times.

    LHS constants for comparison to avoid assignment is a pretty cool habit. perhaps perlmonks should have a "habits & practices" section.

      I'm not sure I completely agree.  The 'x' operator still has to perform a conditional evaluation at a lower level, and 'abs' will certainly chew up some time.  Here's what I get when I benchmark it:

      Program 'benchmark.pl':

      #!/usr/bin/perl -w # Strict use strict; use warnings; # User-defined my $niter = 2000000; # Libraries use Benchmark; # Main program timethis($niter, \&sub1); timethis($niter, \&sub2); # Subroutines sub sub1() { my $noun = 'iteration'; for my $count (0..2) { my $declension = 's' x (abs($count) != 1); my $result = sprintf "$count $noun$declension so far...\n"; } } sub sub2() { for my $count (0..2) { my $s = (1 == $count)? "": "s"; my $result = sprintf "$count iteration$s so far...\n"; } }

      Results:

      [liverpole@diamond<28>]% benchmark.pl timethis 2000000: 25 wallclock secs (20.27 usr + 0.05 sys = 20.32 CPU +) @ 98425.20/s (n=2000000) timethis 2000000: 19 wallclock secs (17.12 usr + 0.01 sys = 17.13 CPU +) @ 116754.23/s (n=2000000)

      Of course, I had to change "print" statements to "sprintf", since the program will be ridiculously I/O-bound otherwise.  But since I had to resort to an absurd iteration count anyway, it probably doesn't matter which you use for most cases.

      Hey, I love your idea about a Perlmonks "habits & practices" section!  If something like that existed, I would reference it all the time.

        well, the abs() call is only there for the case of -1 -- you can take it out to compare against your case, or put some other check in to your case such that -1 == $count behaves the same as 1 == $count. otherwise you're comparing apples & oranges.

        also, my snippet used two interpolations where yours reduced it to one ($noun versus the constant iteration) which doesn't make a huge difference, but again, them citrus fruits... time for me to run home. if you haven't rebenched, I'll set one up that's as parallel as possible except for x vs. ?:

        ps: I don't know how the x operator is implemented, which is why i said "theoretically" faster -- as far as i can tell, there is no need for it to include a branch.

        UP-dilly-DATE : OK, i didn't do it last night, but I did it. I made this small change:

        sub sub1() { for my $count (0..2) { my $declension = 's' x ($count != 1); my $result = sprintf "$count iteration$declension so far...\n" +; } }

        and got ... actually, quite similar results:

        timethis 2000000: 52 wallclock secs (26.95 usr + 0.39 sys = 27.34 CPU +) @ 73152.89/s (n=2000000) timethis 2000000: 38 wallclock secs (25.47 usr + 0.34 sys = 25.81 CPU +) @ 77489.35/s (n=2000000)

        Which is interesting, to me.