Search code examples
perlperformancecode-organization

How do I maintain good code organisation without sacrificing performance?


I subscribe to the idea that variables shouldn't be initialized until right before you're going to use them. It makes it a lot easier to remember what a variable represents if it's by the code that will consume it, and it diminishes the chance that the variable will be misused between initialisation and proper use.

The problems comes when the use of that variable is inside a loop or two. Then, the cost of intialisation gets multiplied and it may begin to impact performance.

Within Perl (or generally, as appropriate), are their any neat little techniques that allow you to place the initialization of a variable within a loop, but such that it only gets initialized on the first pass?

I'd thought of something like:

my $variable = undef;
while ($outer_loop) {
    while ($inner_loop) {
       $variable = $variable || 'initial_value'
    }
}

NB: The implication is that $variable is not reassigned within the loop.

Now maybe it's me, but that seems a little inelegant.

So, here's my question: is there a neater way to do this, or do I just need to get overmyself and compromise on code organisation, or suck up that 'inelegant' solution above?


Solution

  • To address issues in your comment (the variable is computed in a function):

    • A standard technique for optimizing this sort of logic that you want is called memoization (of that function). Among other approaches, Perl has Memoize module, or you can do it yourself.

        use Memoize;
        memoize('slow_function');
        while ($outer_loop) {
            while ($inner_loop) {
                my $variable = slow_function(arguments);
            }
        }
      
    • Also, if the function is always producing 100% identical value (by design) throughout the loop, simply do a poor-mans memoization by initializing the variable in a statement prior to the loop.

      If you have a loop 3 pages long (e.g. so long that having the initialization before the loop is a readability problem compared to inside the loop), you have a bigger coding problem than just the location of the initialization line, and need to re-factor your code in the first place.

      As an aside, if your only concern with placing the variable before the loop is the fact that it destroys the readability context of "this variable is only for use inside this loop", you can easily solve it by either:

      • Having well documented code - either name the variable accordingly, or add a comment to initialization line, or both.

      • Or, by naming a variable something like my $default_value_for_next_loop = long_func(); , and inside the loop actually create a local loop variable initialized from that: my $loop_var = $default_value_for_next_loop;

    Also, as far as your own approach ($variable = $variable || 'initial_value';); I personally find that absolutely elegant and readable, BUT!!! I'm pretty sure that it actually performs worse than a straight-up $variable = $default_value_for_next_loop;, because it has a conditional statement instead of a straight assignment. But I can't be certain without benchmarking.