Closures and Letrec

C

Charles Comstock

Is there a way to create recursive anonymous closures in ruby? For instance
if I write
even = proc {|x| x == 0 ? true : odd(x-1)}
odd = proc {|x| x == 1 ? true : even(x-1)}

In this case even definitely doesn't know about odd, and actually doesn't even
know about even. Odd is aware of even though. At least that's how I have
interpreted how ruby works. We get recursion with full methods, just not with
anonymous procs. Is there any intention for support for this with anonymous
procs? Perhaps though a different syntax? procrec or something?

Charlie
 
J

Jim Weirich

Charles said:
Is there a way to create recursive anonymous closures in ruby? For instance
if I write
even = proc {|x| x == 0 ? true : odd(x-1)}
odd = proc {|x| x == 1 ? true : even(x-1)}

In this case even definitely doesn't know about odd, and actually doesn't even
know about even.

Actually, even does know about even because Ruby sees an assignment to
even. To let even know about odd, do this ...

odd = nil
even = proc {|x| x == 0 ? true : odd.call(x-1) }
odd = proc {|x| x == 0 ? false : even.call(x-1)}

By assigning to odd, ruby now knows that "odd" is a variable, not a
method name. (Notice I changed the definition of odd to avoid infinite
recursion for the false case.)
 
D

Dave Brown

: Is there a way to create recursive anonymous closures in ruby? For instance
: if I write
: even = proc {|x| x == 0 ? true : odd(x-1)}
: odd = proc {|x| x == 1 ? true : even(x-1)}
:
: In this case even definitely doesn't know about odd, and actually doesn't even
: know about even. Odd is aware of even though.

Sure, you just have to remember about The Miracle Of Duck Typing, and
make sure that both your variables are visible to each other.

Since a proc is a method, you can call it. Since an object is an
object, you can send messages to it. One such message is [] (which is
an alias for Proc#call).

Also, I found a bug in your code. :)

$even = proc { |x|
case x
when 0 then true
when 1 then false
else $odd[x-1]
end
}

$odd = proc { |x|
case x
when 0 then false
when 1 then true
else $even[x-1]
end
}

p $odd[3]
p $even[4]
p $odd[4]
p $even[3]

$odd isn't even defined when $even is set, but that doesn't stop
Ruby: it doesn't worry about things like that until you're
actually trying to call methods. By the time it actually gets
around to trying to call methods against odd, odd is defined and
you can call [] with no problems.

--Dave
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
474,141
Messages
2,570,817
Members
47,364
Latest member
Stevanida

Latest Threads

Top