http://www.perlmonks.org?node_id=435241

Tanktalus has asked for the wisdom of the Perl Monks concerning the following question:

This node started out as a reply to Re^2: Using DateTime together with Template::Toolkit. Then I decided it was sufficiently different from that thread...

I'm really curious as to why template modules take hashrefs. I notice most, if not pretty much all, template modules take this view. And it's driving me crazy. Perhaps I really am crazy to want something a bit different, and perhaps someone can set me straight on this.

Most template modules want you to pass in a hash of keys/values, or keys/AoH-refs for looping. My problem with this is that I much, much prefer lazy evaluation. For example, in some code at work, I need to figure out variables for thousands of iterations through this type of evaluation since I took the same idea, figuring that if everyone else was doing it, there was a reason. But only a hundred or so strings needed a lookup, and even then, only one or two of the variables needed to be there at the time. The effort in creating the hash was mostly wasted.

Here's an example of what I'm talking about. I have a list (whether on disk or in a database or in an xml file, whatever - it's been extracted to a list) of files to do something to. However, these files are libraries and executables. And I'm running cross-platform. So, say I have a list like this:

my @files = qw( [%libprefix%]foo[%libsuffix%] Foo[%exesuffix%] foo[%batsuffix%] );
Here, we have a shellscript/batchfile foo which is a wrapper around the Foo executable, which loads the foo library. Each filename is unique - at least on the platforms that I'm familiar with. So we have to come up with each of the variables:
my %params = ( unix => { libprefix => 'lib', exesuffix => '', batsuffix => '', }, aix => { libsuffix => '.a', }, hp => { libsuffix => '.sl', }, linux => { libsuffix => '.so', }, windows => { libprefix => '', libsuffix => '.dll', exesuffix => '.exe', batsuffix => '.bat', }, ); my %real_param; if ($platform =~ /windows/i) { #including Win/ia32, Win/ia64, Win/x86- +64 %real_param = %{$param{windows}}; } elsif ($platform eq 'AIX') { %real_param = (%{$param{unix}}, %{$param{aix}}); } # ...
Rather than doing things this way, I'd rather have a callback. I can go and retrieve the parameter from a database, for example, if, only if, and when it is required. No earlier, and no need to do so if the parameter isn't required. My callback can also use Memoize to cache the value to become faster. I did things this way for Re: String expansion script and am really liking it.

Now, I understand that in some cases, the overhead of calling a sub is greater than the overhead of creating a hash to pass in. But it's not really that difficult to use both. Perl6's multi-subs may make this faster, but even in perl5, checking that you have a CODE ref rather than a HASH ref and doing the right thing is not a significant amount of code.

Is this premature optimisation? Even if it appears this way, is it not more flexible? Any comments?