What are closures, continuations?

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

Joe R. MUDCRAP-CE 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. 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_containers.html#UG
[2]http://ruby-doc.org/core/classes/Continuation.html

One more question – what are lambdas? :wink:

Joe

Joe R. MUDCRAP-CE [email protected] 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-11.html

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.

Joe R. MUDCRAP-CE [email protected] 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.

On 10/27/06, Joe R. MUDCRAP-CE [email protected] 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

matt neuburg wrote:

Joe R. MUDCRAP-CE [email protected] 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

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

Justin C. [email protected] 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 ???

On 10/28/06, Jörg W Mittag [email protected] wrote:

matt neuburg wrote:

Joe R. MUDCRAP-CE [email protected] 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.

On 10/28/06, Simen E. [email protected] wrote:

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.

Right. It’s best just to think of lambda as a way to get anonymous
functions. It’s more or less like Proc.new (close enough).

Closures are a property of functions, but they have much more to do
with lexical scoping. In fact, older lisps didn’t have lexical
closures because because they were dynamically scoped. Also, there is
a mathematical property called closure that is referred to in lisp
texts which has nothing to do with lexical closures.

x = 1
(1..5).each {|i| i + x}

You can use the x variable because the block is a closure. Really,
you don’t think about it too much, as it just does what you would
expect.

Unless you were expecting the wrong thing =)

matt neuburg [email protected] 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)

“Une Bévue” [email protected] wrote:

Justin C. [email protected] 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 ???

There are some similarities but also restrictions. For example you can
only
reference final variables from the current environment which means you
cannot change them. That in turn is typically possible with closures:

irb(main):001:0> def counter(init=0) lambda {|*x| init += x[0]||1} end
=> nil
irb(main):002:0> c = counter
=> #Proc:[email protected]:1(irb)
irb(main):003:0> c[]
=> 1
irb(main):004:0> c[]
=> 2
irb(main):005:0> c[]
=> 3
irb(main):006:0> c[]
=> 4
irb(main):007:0> c[10]
=> 14

In a way every class is a closure as its instances carry around some
state
they can always access. But the term “closure” is generally /not/ used
for
this - this is called “encapsulation”.

Kind regards

robert

Robert K. [email protected] wrote:

In a way every class is a closure as its instances carry around some state
they can always access. But the term “closure” is generally /not/ used for
this - this is called “encapsulation”.

u’re right !

On 10/28/06, Simen E. [email protected] wrote:

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:

This example reminded me of Modula-2’s coroutines. Are these
concepts related somehow?

On Oct 28, 2006, at 10:22 AM, Juan Lupión wrote:

On 10/28/06, Simen E. [email protected] wrote:

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:

This example reminded me of Modula-2’s coroutines. Are these
concepts related somehow?

Since continuations represent the state of the computation including
the call stack, they can be used to implement coroutines. Methods can
suspend computation and pass control around to other methods; when
the continuation is called, computation will resume at the same point.

On 10/28/06, Joe R. MUDCRAP-CE [email protected] wrote:


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

http://onestepback.org/articles/invitationtoruby/reason4.html

Prasaad

On Sat, Oct 28, 2006 at 10:05:18PM +0900, Une Bévue wrote:

matt neuburg [email protected] 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 ???

The former. The lambda calculus was on the scene long before Lisp was a
twinkle in McCarthy’s eye.

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

No it’s not. It was a mathematical formalism for computation. Whatever
gave
you that idea?

Here’s the Wikipedia article:
http://en.wikipedia.org/wiki/Lambda_calculus

K.

This forum is not affiliated to the Ruby language, Ruby on Rails framework, nor any Ruby applications discussed here.

| Privacy Policy | Terms of Service | Remote Ruby Jobs