Florian Gross
10/19/2004 6:16:00 PM
Sam Sungshik Kong wrote:
> Hi, group!
Moin!
> In a language that has Closures, in this case Ruby, I'd write this.
>
> def managers(emps)
> return emps.select {|e| e.isManager}
> end
> </snip>
>
> This is just a block, right?
Yes.
> Is it also a closure?
In Ruby all blocks are also closures, but in that example you wouldn't
need a closure.
Here's a sample that really needs closures to work:
sum = 0
[1, 2, 3].each do |item|
sum += item # access to a variable that is outside of the block
end
This is a closure because you are accessing an outer variable from
within the block.
Blocks in Ruby are a fancy syntax for anonymous functions with closures.
JavaScript's anonymous functions also hold closures.
Let's add a Ruby-like Array#each to JavaScript:
Array.prototype.each = function(block) {
for (var index = 0; index < this.length; ++index) {
var item = this[index]
block(item, index)
}
return(this)
}
Then we can use it like this:
var sum = 0
[1, 2, 3].each(function(item) { sum += item })
Here again the outer variable "sum" gets accessed from within an
anonymous function. For this to work it has to hold a closure.
Back to your sample from earlier:
> def makeCounter
> var = 0
> lambda do
> var +=1
> end
> end
lambda takes a block and converts it into an Object that can be returned
and later invoked via .call. The closure will also get stored.
This lets you increase the var which is scoped locally to makeCounter
from outside of it by calling the lambda.
Here's another example of a closure:
def times_lambda(a)
lambda { |b| a * b }
end
times_5 = times_lambda(5)
times_5.call(4) # => 20
times_5.call(6) # => 30
times_lambda() returns a lambda that holds a reference to the a
parameter of times_lambda() and multiplies it with the b parameter that
is later given to the lambda itself.
Hope this helps. If you still have any questions, feel free to ask.
Regards,
Florian Gross