# [Pdx-pm] [OT] Chrononauts and Perl programming clinic

Curtis Poe cp at onsitetech.com
Thu Oct 24 14:41:27 CDT 2002

```Regrettably, I will not be able to make it the clinic tonight (but if
another one is held and there is a bit more notice, I might even be

In the meantime, if you would like to have your Perl brains stretched, check
out http://perl.plover.com/book/.  This is information on Mark-Jason
Dominus' Perl Advanced Techniques Handbook.  If you subscribe to the mailing
list, you get a link to his current "work in progress" sample chapter.
Right now, he's doing some nifty stuff with iterators that has led me to
create some code to generate Fibonacci numbers.

If you create a Fibonacci series (f(n) = f(n-1) + f(n-2) -- 1,1,2,3,5,8,13
... etc), as you get further along the series, you find that f(n) / f(n-1)
gets fairly close to 1.618034, which is roughly the Fibonaccci number.  Of
search on google), you discover that

1 / f(n) = f(n) - 1 (roughly 0.618034)

And

f(n) * f(n) = f(n) + 1 (roughly 2.618034)

In other words, the number after the decimal point doesn't change.  In the
following code, I have an iterator that produces the Fibonacci series (which
is a nifty trick when one needs to generate an infinite, but precomputing
the list would be a wee bit expensive :), and I use a second iterator which
uses the first iterator to generate numbers closer and closer to the
Fibonacci number.  Finally, I have a couple of "iterator maps" that
transform the iterators into different iterators.  This code uses "bignum",
but it's optional.  If you don't use it, you'll just get less precision and
less interesting results (and there's an "undefined" warning at one point
that I didn't worry about because this was just a quick hack).

MJD's stuff is very interesting so I heartily recommend checking it out!

Tom, I don't suppose I can talk you into an "email" code review, eh? ;)
(no, don't bother.  You might get swamped!  I just wish I could have made it
to the clinic tonight)

#!/usr/bin/perl -w
use strict;
use bignum;
use constant FORMAT => "%12s  %s\n";

sub NEXT (\$) { \$_->() };

sub imap (&\$) {
my (\$transform, \$it) = @_;
return sub {
local \$_ = NEXT \$it;
return unless defined;
return \$transform->(\$_);
}
}

sub fibonacci_series {
my @numbers = (1,1);
return sub {
my \$next = shift @numbers;
push @numbers => \$numbers + \$next;
\$next;
}
}

sub fibonacci_number {
my @numbers = (0,0);
my \$series = fibonacci_series;
return sub {
shift @numbers;
push @numbers => NEXT \$series;
return \$numbers ? \$numbers / \$numbers : undef;
}

}

my \$series     =                  fibonacci_series;
my \$fib        =                  fibonacci_number;
my \$reciprocal = imap { 1 / \$_ }  fibonacci_number;
my \$square     = imap { \$_ * \$_ } fibonacci_number;

for ( 1 .. 50 ) {
printf FORMAT, NEXT \$series,  NEXT \$fib;
printf FORMAT, 'Reciprocal:', NEXT \$reciprocal;
printf FORMAT, 'Square:',     NEXT \$square;
print "\n";
}

```