Lazy Streams and Other Functional Goodies

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

I asked MJD about the idea of doing a "Higher Order Ruby" book. He
said (roughly) that he doesn't know Ruby well enough to be confident
of doing it correctly. If assorted Rubyists translate other examples
from HOP into Perl, however, it might help to make such a book happen
(if not by MJD, then perhaps by someone else...).

-r

···

At 4:24 AM +0900 10/26/05, Louis J Scoras wrote:

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.

--
email: rdm@cfcl.com; phone: +1 650-873-7841
http://www.cfcl.com - Canta Forda Computer Laboratory
http://www.cfcl.com/Meta - The FreeBSD Browser, Meta Project, etc.

In article <p0623090cbf8438394fe6@[192.168.254.205]>,

···

Rich Morin <rdm@cfcl.com> wrote:

At 4:24 AM +0900 10/26/05, Louis J Scoras wrote:

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.

I asked MJD about the idea of doing a "Higher Order Ruby" book. He
said (roughly) that he doesn't know Ruby well enough to be confident
of doing it correctly. If assorted Rubyists translate other examples
from HOP into Perl, however, it might help to make such a book happen
(if not by MJD, then perhaps by someone else...).

Or how about a webpage somewhere where we could put Ruby translations with
some comments. I've been intrigued by the book when I've seen it at
Powell's, but it hurts my eyes too much to look at Perl these days to
consider buying it. If there was a website with Ruby examples, that would
certainly help.

Phil

In article <p0623090cbf8438394fe6@[192.168.254.205]>,

I asked MJD about the idea of doing a "Higher Order Ruby" book. He
said (roughly) that he doesn't know Ruby well enough to be confident
of doing it correctly.

Really it's more that I know Ruby badly enough to be confident of
doing it incorrectly. Evern though every technique in my book is
well-known in the Lisp world, my book could not have been written by
someone who was an expert only on Lisp, because it is very much about
Perl. It had to be written by a Perl expert.

Someone could write a similar book about Ruby, but unless it was
written by a Ruby expert, it would be a pretty bad book.

If assorted Rubyists translate other examples
from HOP into Perl, however,

Folks might want to glance at Sean Burke's "Higher-Order Javascript"
project pages:

        Higher Order JavaScript

···

Rich Morin <rdm@cfcl.com> wrote:

Phil Tomson ha scritto:

In article <p0623090cbf8438394fe6@[192.168.254.205]>,

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.

I asked MJD about the idea of doing a "Higher Order Ruby" book. He
said (roughly) that he doesn't know Ruby well enough to be confident
of doing it correctly. If assorted Rubyists translate other examples

from HOP into Perl, however, it might help to make such a book happen

(if not by MJD, then perhaps by someone else...).

Or how about a webpage somewhere where we could put Ruby translations with some comments.

+1, actually I was doing this. Maybe we could just use a wiki section?

Anyway it is just fun to see that the first 4/5 chapters are actually no brainer in ruby or just seen on ruby-talk regularly (i.e. HOFs, iterators, memoization, decision tables).

> I've been intrigued by the book when I've seen it at

Powell's, but it hurts my eyes too much to look at Perl these days to consider buying it. If there was a website with Ruby examples, that would certainly help.

Phil

hey, I don't even really know perl, I am continuosly thinking "wow, this is too painful!" whn seeing things like coderefs :slight_smile:

···

Rich Morin <rdm@cfcl.com> wrote:

At 4:24 AM +0900 10/26/05, Louis J Scoras wrote:

Mark Jason Dominus wrote:

Someone could write a similar book about Ruby, but unless it was
written by a Ruby expert, it would be a pretty bad book.

Classic example of this: Numerical Recipes in _________

The "C" version may as well just have been piped through some poorly hacked together C -> FORTRAN translator.

That said, I'd love this book. Someone do it so I can give you my money.

--Steve

> Or how about a webpage somewhere where we could put Ruby translations
with
> some comments.

+1, actually I was doing this. Maybe we could just use a wiki section?

Actually, this is what MJD is doing with the book: he's in the process of
getting it into a wiki now. Although it will, of course, be in perl. It
would be excellent to have ruby translations for most of the examples.

Anyway it is just fun to see that the first 4/5 chapters are actually no

brainer in ruby or just seen on ruby-talk regularly (i.e. HOFs,
iterators, memoization, decision tables).

Exactly. A lot of this is already commonplace in ruby. Some of the later
material might be more interesting from a ruby perspective.

···

On 10/26/05, gabriele renzi <surrender_it@-remove-yahoo.it<http://remove-yahoo.it>> wrote:

Mark Jason Dominus wrote:
> Someone could write a similar book about Ruby, but unless it was
> written by a Ruby expert, it would be a pretty bad book.

Classic example of this: Numerical Recipes in _________

The "C" version may as well just have been piped through some poorly
hacked together C -> FORTRAN translator.

I expect you mean C <- FORTRAN, or is this the same confusion as with
the ->(){} operator :wink:

Regards,

Brian

···

On 02/11/05, Stephen Waits <steve@waits.net> wrote:

That said, I'd love this book. Someone do it so I can give you my money.

--Steve

--
http://ruby.brian-schroeder.de/

Stringed instrument chords: http://chordlist.brian-schroeder.de/