What are closures, continuations?

  • Thread starter Joe Ruby MUDCRAP-CE
  • Start date
J

Joe Ruby MUDCRAP-CE

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
 
J

Justin Collins

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

matt neuburg

Joe Ruby MUDCRAP-CE said:
- 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.
 
M

matt neuburg

Joe Ruby MUDCRAP-CE said:
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.
 
S

Simen Edvardsen

- 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
 
S

Simen Edvardsen

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.


--=20
- Simen
 
U

Une Bévue

Justin Collins said:
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 ???
 
U

Une Bévue

matt neuburg said:
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)
 
S

Sylvain Joyeux

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
 
L

Louis J Scoras

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 =)
 
R

Robert Klemme

Une Bévue said:
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:0x003a6254@(irb):1>
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
 
U

Une Bévue

Robert Klemme said:
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 !
 
J

Juan Lupión

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?
 
B

Brad Ediger

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

Since continuations represent the state of the computation including =20
the call stack, they can be used to implement coroutines. Methods can =20=

suspend computation and pass control around to other methods; when =20
the continuation is called, computation will resume at the same point.
 
K

Keith Gaughan

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.
 

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
473,792
Messages
2,569,639
Members
45,351
Latest member
RoxiePulli

Latest Threads

Top