I personally believe that a nice example can be found in some code (link @ GG) I posted in clpmisc some time ago.

(Minimal) premise:

On Fri, 05 Oct 2007 16:49:31 -0500, "Mumia W." <paduille.4061.mumia.w+nospam@earthlink.net> wrote: >I know the mean can be calculated "on the fly"--without storing all o +f >the values to be examined, but I can't see how this is to be done wit +h >the median; I don't think it's possible. Sure it is possible:

Code:

#!/usr/bin/perl use strict; use warnings; use List::Util 'sum'; use constant TESTS => 20; use Test::More tests => TESTS; sub naive { my @arr = map +($_) x $_[$_], 0..$#_; @arr % 2 ? @arr[(@arr-1)/2] : (@arr[@arr/2 - 1] + @arr[@arr/2])/2; } sub findidx { my $i=shift; ($i -= $_[$_])<0 and return $_ for 0..$#_; } sub smart { my $t=sum @_; $t%2 ? findidx +($t-1)/2, @_ : (findidx($t/2-1, @_) + findidx($t/2, @_))/2; } for (1..TESTS) { my @a=map int rand 10, 0..5; is smart(@a), naive(@a), "Test @a"; } __END__

Here, if I were not to have findidx() as a separate sub but inline its code/logic into smart(), I would probably do it like thus:

sub smart { my $t=sum @_; if ($t%2) { my $i=($t-1)/2; ($i -= $_[$_])<0 and return $_ for 0..$#_; } else { my $i=$t/2-1; my ($found1, $found2); for (0..$#_) { ($found1=$_), last if ($i -= $_[$_])<0; } my $j=$t/2; for (0..$#_) { ($found2=$_), last if ($j -= $_[$_])<0; } return ($found1+$found2)/2; } }

Of course there are other WTDI as usual, however one cannot but notice that in this particular case not only did factoring code away in a sub reduce duplication, but it even gave one the possibility of applying some syntactic sugar that makes code overall more terse and clear.

Note: I had and still have the overall impression that when in smart() it happens that t%2 == 0, one could avoid basically doing twice the same loop - but I had tried one or two approaches that seemed obvious to me, and they failed. I posted the code as is seen above because mine was a proof of concept anyway. I guess something subtle and simple (a posteriori) is baffling me. Of course, this is a whole another story...

Update: the twin for loops look really awful - thus YAWTDI for smart() that I would probably favour is:

sub smart { my $t=sum @_; if ($t%2) { my $i=($t-1)/2; ($i -= $_[$_])<0 and return $_ for 0..$#_; } else { my $acc=0; for my $i ($t/2-1, $t/2) { for (0..$#_) { ($acc += $_), last if ($i -= $_[$_])<0; } } return $acc/2; } }

Update: switched from spoiler tags around the minimal description to readmore at Argel's request.


In reply to Re^2: when to use subroutine by blazar
in thread when to use subroutine by convenientstore

Title:
Use:  <p> text here (a paragraph) </p>
and:  <code> code here </code>
to format your post, it's "PerlMonks-approved HTML":



  • Posts are HTML formatted. Put <p> </p> tags around your paragraphs. Put <code> </code> tags around your code and data!
  • Titles consisting of a single word are discouraged, and in most cases are disallowed outright.
  • Read Where should I post X? if you're not absolutely sure you're posting in the right place.
  • Please read these before you post! —
  • Posts may use any of the Perl Monks Approved HTML tags:
    a, abbr, b, big, blockquote, br, caption, center, col, colgroup, dd, del, details, div, dl, dt, em, font, h1, h2, h3, h4, h5, h6, hr, i, ins, li, ol, p, pre, readmore, small, span, spoiler, strike, strong, sub, summary, sup, table, tbody, td, tfoot, th, thead, tr, tt, u, ul, wbr
  • You may need to use entities for some characters, as follows. (Exception: Within code tags, you can put the characters literally.)
            For:     Use:
    & &amp;
    < &lt;
    > &gt;
    [ &#91;
    ] &#93;
  • Link using PerlMonks shortcuts! What shortcuts can I use for linking?
  • See Writeup Formatting Tips and other pages linked from there for more info.