Name

Yet Another Perl 6 Operator: Reduce Operators - Part II

Version

Maintainer: Adriano Ferreira <ferreira@cpan.org>
Date: 28 Dec 2007
Last Modified: 28 Dec 2007
Number: 17
Version: 1
Status: Draft

Body

In a previous article , we introduced the reduction operators (like '[*]' and '[~]') which produced list operators from infix operators (like '*' and '~').

There is a variant of the reduction operator that operates over its list argument producing all intermediate results along with the final result of the ordinary reduction.

[\+] 1..5   # (1, 3, 6, 10, 15)

which is equivalent to

([+] 1), 
([+] 1, 2), 
([+] 1, 2, 3),
([+] 1, 2, 3, 4),
([+] 1, 2, 3, 4, 5)

The above decomposition illustrates that the visual picture of a triangle in the reduce operator (eg, '[\+]') is not accidental.

The triangular reduction lazily generates its resulting list, so that it can be applied to infinite lists.

[\*] 1..*   # (1, 2, 6, 24, ...)

As many other Perl 6 operators, this one has a functional flavor which may estimulate some Haskellish solutions to some problems. A (rather contrived) application example is to implement a mkpath function (similar to the one provided by the Perl 5 module File::Path ) with a mkdir builtin.

sub mkpath (Str $path) {

  # split 'a/b/c' into ( 'a/', 'b/', 'c' )
  my @segments = $path.split( /<!after '\/'>/ );

  for =[\~] @segments {
    # path exists as dir or create it
    .:d || .mkdir;
  }    
}

This will create the directories 'a/', 'a/b/', and 'a/b/c' if they do not exist yet.

See Also

Reduce Operators - Part I

$Revision$