<?xml version="1.0" encoding="windows-1252"?>
<node id="136663" title="Re: Functional perl please" created="2002-01-06 07:56:27" updated="2005-07-29 17:07:43">
<type id="11">
note</type>
<author id="43894">
ariels</author>
<data>
<field name="doctext">
&lt;p&gt;
Here's one example. The &lt;a href="http://www.everything2.com/?node=hamming%20sequence"&gt;Hamming sequence&lt;/a&gt; is the sequence of numbers whose prime factors are only 2, 3 and 5, in ascending order. Writing a program to print out the sequence is non-trivial (we exclude "solutions" which must store the entire sequence in a large array and the like). It used to be the poster example of co-routines, but current style more likely favours a functional program using streams and (somewhat) lazy evaluation.
&lt;/p&gt;
&lt;p&gt;
Read about streams in &lt;a href="http://mitpress.mit.edu/sicp/full-text/book/book-Z-H-24.html#%_sec_3.5"&gt;this chapter&lt;/a&gt; of &lt;a href="http://mitpress.mit.edu/sicp"&gt;Structure and Interpretation of Computer Programs&lt;/a&gt;. The program below is a translation to Perl of a streams-based program to print out the Hamming sequence.
&lt;/p&gt;
&lt;blockquote&gt;&lt;code&gt;
#!/usr/local/bin/perl -w
# Output the Hamming sequence
use strict;

package Stream;

sub new {
  my ($class, $hd, $tl) = @_;
  $class = ref $class || $class;
  bless { _hd =&gt; $hd, _tl =&gt; $tl }, $class
}

sub head {
  my $self=shift;
  $self-&gt;{_hd}
}

sub tail {
  my $self = shift;
  $self-&gt;{_tl} = $self-&gt;{_tl}-&gt;()
    if ref $self-&gt;{_tl} eq 'CODE';
  $self-&gt;{_tl}
}

sub exec {
  my ($self, $code, $n) = @_;
  for my $i (1..$n) {
    $code-&gt;($self-&gt;head);
    $self = $self-&gt;tail
  }
}


package main;

sub merge {
  my ($a, $b) = @_;
  return ($a-&gt;head == $b-&gt;head) ?
    new Stream($a-&gt;head, sub { merge($a-&gt;tail, $b-&gt;tail) }) :
      ($a-&gt;head &lt; $b-&gt;head) ?
	new Stream($a-&gt;head, sub { merge($a-&gt;tail, $b) }) :
	  new Stream($b-&gt;head, sub { merge($a, $b-&gt;tail) });
}

sub mult {
  my ($a, $s) = @_;
  return new Stream($a*$s-&gt;head, sub { mult($a,$s-&gt;tail) });
}


my $hamming;
$hamming = new Stream(1,
                      sub {
                        merge( mult(2, $hamming),
                               merge(mult(3, $hamming),
                               mult(5, $hamming)))
		      }
		     );

my @x;
$hamming-&gt;exec(sub { push @x, shift }, 1000);

print "@x\n";
&lt;/code&gt;&lt;/blockquote&gt;
&lt;hr /&gt;
&lt;b&gt;EDIT&lt;/b&gt; (20020506): fix indentation (Perlmonks does horrible things to tabs; glad it's not Pythonmonks).
</field>
<field name="root_node">
136017</field>
<field name="parent_node">
136017</field>
</data>
</node>
