in reply to when to use subroutine

When you can point to a chunk of code that could stand on its own and give it a meaningful name, you've found a subroutine. Make it a subroutine.

Replies are listed 'Best First'.
Re^2: when to use subroutine
by blazar (Canon) on Oct 29, 2007 at 13:18 UTC

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

    (Minimal) premise:

    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.

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