note
BrowserUk
<blockquote><i>e evenly obvious, although there is still no comment?</i></blockquote>
<p>First, almost a side-issue here, but an important one. My personal take on comments is expressed at length [877916|here] and [877922|here]; but can be summarised by saying that I think that for the most part comments in source code are a counter-productive waste of time, energy, resources and therefore, money.
<P>That said, in the isolated form, I find your self-documenting code a highly readable, fine attempt at the art.
<P>But ... it only works because it is in isolation of a context.
<P>For example, <c>prepend_yearmonth()</c> requires to close over <c>%months</c>. In a short script, the hash might be a package global and declared above the declaration of the subroutines; the actual sort is part of the package level code and everything's hunky-dory.
<P>But now put the sort inside a subroutine -- say, part of the logic of an object's method call. And the hash being referenced by the sort is a part of that object's instance data. Now there is simply no way to define those utility subs to close over the required reference hash.
<P>And that's the crux of the problem that anonymous lambda's address. They allow the programmer to define callback code <b>in the context of its use</b>, thus availing it of access to everything that is in scope at that point. Named-subroutines cannot do this -- in Perl at least -- because any closures used by subs declared in a nested context will result in the infamous:<code>
sub x{ my $y; sub z{ say $y; } };;
Variable "$y" will not stay shared at ...
</code>
<p>If you feel it is necessary to (self)document the use pattern of the GRT -- and I can make a strong case that it is better for programmers to learn the pattern than to have it hidden from them -- then I would perhaps suggest something along the lines of:<code>
#! perl -slw
use strict;
use GRT; # contains:
#sub GRT::prefix(&@) { my $code = shift; map &$code, @_ }
#sub GRT::discard(&@) { my $code = shift; map &$code, @_ }
my %months = (
FY => 0,
Jan => 1, Feb => 2, Mar => 3, Apr => 4, May => 5, Jun => 6,
Jul => 7, Aug => 8, Sep => 9, Oct => 10, Nov => 11, Dec => 12,
);
print for GRT::discard{
unpack 'x[nn]A*'
} sort{
$b cmp $a
} GRT::prefix{
my( $alpha, $num ) = m[^(\S+?)\s*(\d+)$];
$num += 2000 if $num <= 49;
$num += 1900 if $num <= 99;
pack 'nnA*', $num, $months{ $alpha }, $_;
} <DATA>;
__DATA__
Apr 2006
FY05
FY98
FY04
Dec 2007
Jan 1997
Jan 1998
Dec 1998
</code>
<P>The key points of this are:
<ol><li>The GRTsubs can be imported from a module.
</li><li>That module can document the GRT and the use of the helper functions.
</li><li>The purely implementation elements, the [map]s, are hidden.
</li><li>The [sort] comparator block can be specified to invert the order of the sort.
</li><li>It can be constructed at any scope and make full use of the context.
</li></ol>
<p>Of course, it is also substantially slower and little more than a pair of 'active comments'; which leaves me believing that the simple addition of a couple of comments achieves the same thing:<code>
print for map{
## remove them once sorted
unpack 'x[nn]A*', $_
} sort map {
## prefix year & month in binary form
my( $alpha, $num ) = m[^(\S+?)\s*(\d+)$];
$num += 2000 if $num <= 49;
$num += 1900 if $num <= 99;
pack 'nnA*', $num, $months{ $alpha }, $_;
} <DATA>;
</code>
<div class="pmsig"><div class="pmsig-171588">
<hr />
<font size=1 >
<div>With the rise and rise of 'Social' network sites: 'Computers are making people easier to use everyday'</div>
<div>Examine what is said, not who speaks -- Silence betokens consent -- Love the truth but pardon error.</div>
<div>"Science is about questioning the status quo. Questioning authority". </div>
<div>In the absence of evidence, opinion is indistinguishable from prejudice.
</div>
</font>
</div></div>
1055553
1055789