[lnkForumImage]
TotalShareware - Download Free Software

Confronta i prezzi di migliaia di prodotti.
Asp Forum
 Home | Login | Register | Search 


 

Forums >

comp.lang.ruby

What are closures, continuations?

Joe Ruby

10/27/2006 8:31:00 PM

I've seen these mentioned in various places. From what I can tell:

- Ruby has closures -- which seem to be returning procs from functions?
- Continuations may be planned for a future release of Ruby.

If anybody can elaborate/correct, please feel free! Also, how would each
be useful?

Thanks,
Joe

--
Posted via http://www.ruby-....

22 Answers

Justin Collins

10/27/2006 8:39:00 PM

0

Joe Ruby MUDCRAP-CE wrote:
> I've seen these mentioned in various places. From what I can tell:
>
> - Ruby has closures -- which seem to be returning procs from functions?
> - Continuations may be planned for a future release of Ruby.
>
> If anybody can elaborate/correct, please feel free! Also, how would each
> be useful?
>
> Thanks,
> Joe
>

Closures are tricky, but you can think of them as blocks of code, or a
way of making code a first-class object. Or as anonymous functions. Or
as lambdas. There is a lot of documentation on them, I'd start with the
Pickaxe book if you have it, or the online version if you do not.[1]
Then google for "ruby blocks" and read what you can find to clarify.
Also search this list for past discussions.

Continuations are currently available in Ruby[2], although, from what I
understand, they are not widely used. There was a thread earlier about
YARV (the "engine" for the next version of Ruby) not yet supporting
continuations. That might be what you are thinking of.

-Justin

[1]http://ruby-doc.org/docs/ProgrammingRuby/html/tut_containe...
[2]http://ruby-doc.org/core/classes/Continu...



Joe Ruby

10/27/2006 8:46:00 PM

0

One more question -- what are lambdas? ;)

Joe

--
Posted via http://www.ruby-....

matt

10/27/2006 9:29:00 PM

0

Joe Ruby MUDCRAP-CE <joeat303@yahoo.com> wrote:

> - Ruby has closures -- which seem to be returning procs from functions?
> - Continuations may be planned for a future release of Ruby.

Continuations are hard, so I won't touch them. Very good examples here:

<http://www.rubycentral.com/faq/rubyfaq-1...

Closures are something I can handle (I discuss them in my AppleScript
book, for example).

* A binding is an association of a name and a value.

* A free variable is a variable defined in a surrounding scope.

* A closure is block of code where free variables are bound in
accordance with the surrounding scope and (this is important) retain
that binding.

So, for example:

var = 7
p = Proc.new {puts var}
def hereGoesNothing
var = "yoho"
yield
end
hereGoesNothing &p # => 7
var = 200
hereGoesNothing &p # => 200

The block "{puts var}" is a closure. Its "var" is a free variable and is
therefore bound to the "var" in the surrounding scope, which is the
"var" set to 7 in the first line. So what we see is that the "var"
inside hereGoesNothing makes no difference. As we change the top-level
"var", its new value is used each time we execute the block. It doesn't
matter what we do with p; it will retain its bindings.

Here's another example (more like your procs from functions idea):

def proc_maker
var = 7
Proc.new {puts var}
end
p = proc_maker
p.call # => 7

Here, "var" exists only inside the method "proc_maker". When we come to
call p, there is no "var"! But that doesn't matter; the proc "{puts
var}" has retained the binding of "var" with 7 from the place where it
was bound to start with, inside the method.

m.

--
matt neuburg, phd = matt@tidbits.com, http://www.tidbits...
Tiger - http://www.takecontrolbooks.com/tiger-custom...
AppleScript - http://www.amazon.com/gp/product/...
Read TidBITS! It's free and smart. http://www.t...

matt

10/27/2006 9:29:00 PM

0

Joe Ruby MUDCRAP-CE <joeat303@yahoo.com> wrote:

> One more question -- what are lambdas?

This is a term from LISP. It basically just means a function that you
can define and then pass around and call. In my previous example (about
closures), the thing in curly braces, "{puts var}", was effectively a
lambda.

var = 7
p = Proc.new {puts var}
def hereGoesNothing
var = "yoho"
yield
end
hereGoesNothing &p # => 7
var = 200
hereGoesNothing &p # => 200

###

def proc_maker
var = 7
Proc.new {puts var}
end
p = proc_maker
p.call # => 7

In the first example, I form the function, I assign it to a variable,
and hand it (twice) to a method (hereGoesNothing) which calls it
(yield). In the second example, I form the function and hand it out as
the result of a method (proc_maker), assign it to a variable, and call
it (call).

LISPers like to celebrate this ability (among others) to treat a
function just like any other Thing, passing it around and so forth, by
chanting a poem (with apologies to JRR Tolkien) whose last three lines
are:

One Thing to name them all, One Thing to define them,
One Thing to place them in environments and bind them,
In the Lambda Order they are all first-class.

m.


--
matt neuburg, phd = matt@tidbits.com, http://www.tidbits...
Tiger - http://www.takecontrolbooks.com/tiger-custom...
AppleScript - http://www.amazon.com/gp/product/...
Read TidBITS! It's free and smart. http://www.t...

Simen

10/27/2006 10:29:00 PM

0

On 10/27/06, Joe Ruby MUDCRAP-CE <joeat303@yahoo.com> wrote:
> - Continuations may be planned for a future release of Ruby.
>
> If anybody can elaborate/correct, please feel free! Also, how would each
> be useful?
>

Continuations represent "the rest of the computation". Try googling
continuations and continuation passing style. Here's an example of how
closures and continuations are useful, cooperative threading:

# threading.rb:

class Scheduler
def initialize
@threads = []
end

def yield
callcc do |continuation|
@threads << continuation
schedule
end
end

def spawn
callcc do |continuation|
@threads << continuation
yield
schedule
end
end

def schedule
return if @threads.empty?
@threads.shift.call
end
end

def thread
yield Scheduler.new
end

if $0 == __FILE__
puts "Testing spawning and stuff..."

thread { |scheduler|
puts "In parent"
scheduler.spawn {
puts "In child"
scheduler.yield
puts "In child again"
}
puts "In parent again"
scheduler.yield
}
end

$ ruby threading.rb
Testing spawning and stuff...
In parent
In child
In parent again
In child again

> Thanks,
> Joe
>
> --
> Posted via http://www.ruby-....
>
>

--
- Simen

Jörg W Mittag

10/28/2006 10:47:00 AM

0

matt neuburg wrote:
> Joe Ruby MUDCRAP-CE <joeat303@yahoo.com> wrote:
>> One more question -- what are lambdas?
> This is a term from LISP.

Actually, it is a term from Lambda Calculus, which existed long before
LISP or even computers.

jwm

Simen

10/28/2006 12:38:00 PM

0

On 10/28/06, Jörg W Mittag <Joerg.Mittag@web.de> wrote:
> matt neuburg wrote:
> > Joe Ruby MUDCRAP-CE <joeat303@yahoo.com> wrote:
> >> One more question -- what are lambdas?
> > This is a term from LISP.
>
> Actually, it is a term from Lambda Calculus, which existed long before
> LISP or even computers.
>

The lambda calculus took it from the Greek Alphabet, who adapted it
from the Phoenecian Alphabet, and so on (you could keep going
forever). Actually closures are never called "lambdas", at least not
in any writing I've read on Lisp, it's just a symbol used to denote a
closure.

> jwm
>
>


--
- Simen

pere.noel

10/28/2006 1:00:00 PM

0

Justin Collins <collinsj@seattleu.edu> wrote:

> Closures are tricky, but you can think of them as blocks of code, or a
> way of making code a first-class object. Or as anonymous functions.

could we say they work as anonymous class in java ???

pere.noel

10/28/2006 1:00:00 PM

0

matt neuburg <matt@tidbits.com> wrote:

> This is a term from LISP. It basically just means a function that you
> can define and then pass around and call.

is that "lambda" name derived from lambda calculus in modern logic, or
is it the reverse, lambda calculus deriving from lisp work ???

(i would think so because lambda calculus is aimed toward automatic
comilation from function down to machine language)

Sylvain Joyeux

10/28/2006 1:02:00 PM

0

> The lambda calculus took it from the Greek Alphabet, who adapted it
> from the Phoenecian Alphabet, and so on (you could keep going
> forever). Actually closures are never called "lambdas", at least not
> in any writing I've read on Lisp, it's just a symbol used to denote a
> closure.
A lambda is not necessary a closure. A lambda is an anonymous function (and
as you will see later, this is *not* a block or a Proc.new { ... })

The meaning of the lambda operator in languages like Ruby is "build an
anonymous function", and it does come from lambda calculus. Lambda (in
Ruby) is building a function (actually, a Proc) from a block.
The "closure" part comes from the fact that blocks are closures. If blocks
weren't closures, lambdas would not be either.

Calling 'return' in Proc.new { return }.call fails with LocalJumpError
while it works in lambda { return }.call . Kernel#lambda really changed
the block into a function.

My 2 cents
--
Sylvain Joyeux