------art_20365_32955441.1130268274416
Content-Type: text/plain; charset=ISO-8859-1
Content-Transfer-Encoding: quoted-printable
Content-Disposition: inline

Hey all;

A really good book I read a little while ago is "Higher Order Perl", by Mark
Jason Dominus. Yes, yes. It is a book about perl, but more importantly its
about doing neat things with closures. There was a thread recently about
functional techniques in Ruby, and some of the ideas in MJDs book can be
ported over pretty easily. In fact, doing this in ruby seems a bit more
natural IMHO.

Anyway, I did a quick rewrite of the lazy (infinite) streams from HOP.

# Adapted from Higher-Order Perl by Mark Dominus, published by Morgan
Kaufmann
# Publishers, Copyright 2005 by Elsevier Inc

class LazyStream

def initialize(h,&bloc)
@head = h
@tail = bloc
end

attr_reader :head

def tail
if @tail.respond_to? :call
@tail = @tail.call
end
@tail
end

def exhausted?
false
end

def self.upto(m, n)
return LazyStream::Terminator.new if m > n
new(m) do
self.upto(m + 1, n)
end
end

def self.upfrom(n)
new(n) do
self.upfrom(n+1)
end
end

def take(n)
stream = self.dup
list = []
n.times do
return list unless stream
list << stream.head
stream = stream.tail
end
list
end

def transform &bloc
t = yield head
LazyStream.new(t) do
tail.transform(&bloc)
end
end

def filter &bloc
s = self.dup
until s.exhausted? || yield(s.head)
s = s.tail
end
return LazyStream::Terminator.new if s.exhausted?
LazyStream.new(s.head) do
s.tail.filter(&bloc)
end
end

end

class LazyStream::Terminator < LazyStream
def initialize; end
def head; nil; end
def tail; nil; end
def transform; self; end
def filter; self; end
def exhausted?; true; end
def take(n); nil; end
end

This lets you do some cool stuff like representing all positive integers:

pos_ints = LazyStream.upfrom 1
p pos_ints.take(10)

Back in school I remember having to write a program to generate the first
100 prime numbers. Back then I did it in haskell, which gives you lazy
evaluation for free. But with the above class you can do this to implement
the Sieve of Eratosthenes:

def seive(s)
p = s.head
LazyStream.new(p) do
seive(s.tail.filter {|n| n % p != 0})
end
end

def primes
seive LazyStream.upfrom(2)
end

Or you can use the recursive definition rather than the above generator,
which is faster:

$primes = LazyStream.new(2) { LazyStream.upfrom(3).filter{|n| is_prime? n} }

def is_prime?(x)
r = lambda do |stream|
h = stream.head
return false if (x % h == 0)
return true if (h ** 2 > x)
r.call(stream.tail)
end
r.call($primes)
end

Anyway, sorry for the long post. I guess my point was to ask if anybody is
getting use out of techniques usually associated with "functional
languages?" From the Ruby I've seen--still pretty new--it seems that
closures for callbacks are pretty common, and for resource management. What
about things like Currying? Functional composition?


--
Lou

------art_20365_32955441.1130268274416--