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.
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.
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.
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
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.
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.
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.
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:
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”.
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”.
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?
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.