From Novice to Adept: Functional versus Structural Code

| 1 Comment

My recommendation against explicit scalar in Embracing Idioms gathered some attention. "It's clearer to read," said some people. "It's more obvious what I mean," said others.

The best advice I can give any fledgling Perl 5 programmer is to read anything Mark Jason Dominus writes, especially his Higher Order Perl. That book may be daunting, so for now start with Ovid's journal entry about synthetic classes. He quotes MJD, who responds himself:

I realized after a couple of years that architects have ... "structural" and "functional" elements.

One of the characteristics of novice code is that it focuses on structural elements. When someone says "You write Perl like a C programmer", it often means that you're doing too much work in your loops:

for (my $i = 0; $i < @elems; ++$i)
{
    my $elem = $elems[$i];
    say "$elem";
}

Compare that to the Perlish use of iteration:

for my $elem (@elems)
{
    say $elem;
}

... or the postfix iteration, implicit topic form:

say for @elems;

Sometimes you can even get away with the version which exploits list context:

say @elems;

(Though note that the current output record separator has a greater effect on the functional equivalence of the final version.

In this case, the structure of the iteration is less important than the function of printing every element of the array. While for people learning Perl, the multiple seemingly-equivalent options seem overwhelming, daunting with fragmentation possibilities, experienced Perl programmers can choose the form which best expresses the intended function while minimizing synthetic code.

Perhaps it's clearer to explain why map and grep are important.

Perl 5's map iterates over a list and produces a list. That's it. You can produce a list of the first ten square numbers with the code:

my @squares = map { $_ * $_ } 1 .. 10;

The equivalent iteration version might be:

my @squares;

for my $i ( 1 .. 10 )
{
    push @squares, $i * $i;
}

If you're not familiar with map, the first version may seem inscrutable and the second comforting. Yet compare the amount of structural code in the second example. The iteration is explicit. Creating list elements is explicit. Creating the resulting list is explicit. Extending the resulting list is explicit.

Similarly, grep removes synthetic code:

my @primes = grep { is_prime( $_ ) } @maybe_primes;

... versus:

my @primes;

for my $maybe_prime (@maybe_primes)
{
    next unless is_prime( $maybe_prime );
    push @primes, $maybe_prime;
}

Perl 6 takes this further by introducing a concept of metaoperators (see Perl 6 Synopsis 3), which allow the use of any existing operator -- built in or user-defined -- to reduce or distribute over a list (in parallel, even) or more.

This is not to say that it's bad or wrong to use structural code, especially as a novice. Learning to program takes work. Learning syntax and design and the interaction of symbols in symbolic computation is complex. Even so, one of your goals should be to reach the point where you can evaluate syntax and idioms and choose the ones which best clarify the intent and function of your code, rather than the ones which emphasize the structure of how you accomplish that goal.

1 Comment

The more functional tools 'map' and 'grep' were sort of foreign for me at first, but once one understands what they do, they are incredible useful. I reach for map all the time, not least to peer into data structures with a 'print map { $_ . "\n" } @stuff'. Using grep with a subroutine is an idiom I should use more often as well.

Modern Perl: The Book

cover image for Modern Perl: the book

The best Perl Programmers read Modern Perl: The Book.

sponsored by the How to Make a Smoothie guide

Categories

Pages

About this Entry

This page contains a single entry by chromatic published on November 5, 2009 5:59 PM.

From Novice to Adept: The Act of Naming was the previous entry in this blog.

A Language's Tools (CPAN versus IDEs) is the next entry in this blog.

Find recent content on the main index or look in the archives to find all content.


Powered by the Perl programming language

what is programming?