Closures / lambda question

This is something I don’t understand, and did not understand when I
studied LISP. I just watched Dave T.’ presentation, “Extending Ruby
for Fun and Profit”, which I by the way highly recommend to everyone who
hasn’t seen it…
And he has the following example:

def proc_with_enclosing_scope
name = “Ruby”
lambda { puts name }
end

the_proc = proc_with_enclosing_scope
the_proc.call

name = “Java”
the_proc.call


I don’t understand what Ruby is doing / what happens.
First question: the “name” variable is defined inside the method
proc_with_enclosing_scope, so why would changing the name outside the
method make a difference in the first place?

Second question: I tried to type this straight into irb and made a small
typo, so it came out as such -

def proc_with_enclosing_scope
name = “Ruby”
lamda { puts name }
end
=> nil

the_proc = proc_with_enclosing_scope
NoMethodError: undefined method lamda' for main:Object from (irb):23:inproc_with_enclosing_scope’
from (irb):25

So… When the_proc gets assigned the … Value of the method
running… (?) What does it get assigned?

And lastly… I know that “proc” exists, too. What is the difference /
what does it do?

I thank you very much in advance for the enlightenment you will provide
:slight_smile:

I think what Dave was trying to illustrate with this example is that
even
though the method that you’re calling has gone out of scope that it
still
retains the value of the variable defined inside.

Whats fascinating about this simple example is the fact that the method
which is assigned to a remembers the context of everything defined
internally. Think about that for a second. In languages that do not
support closures the values of the properties defined are lost until the
next time the method is called, however closures not only remember the
values of their properties after the function goes out of scope but the
context in which they were originally defined. Its a pretty simple
concept
but a very powerful one at the same time.

Aldric G. wrote:

This is something I don’t understand, and did not understand when I
studied LISP. I just watched Dave T.’ presentation, “Extending Ruby
for Fun and Profit”, which I by the way highly recommend to everyone who
hasn’t seen it…
And he has the following example:

def proc_with_enclosing_scope
name = “Ruby”
lambda { puts name }
end

the_proc = proc_with_enclosing_scope
the_proc.call

name = “Java”
the_proc.call


I don’t understand what Ruby is doing / what happens.
First question: the “name” variable is defined inside the method
proc_with_enclosing_scope, so why would changing the name outside the
method make a difference in the first place?

It doesn’t. Did you try the code? Both instances of the_proc.call
return “Ruby”. I assume the ‘name=“Java”’ line is just there to point
out that it’s not the same variable.

Second question: I tried to type this straight into irb and made a small
typo, so it came out as such -

def proc_with_enclosing_scope
name = “Ruby”
lamda { puts name }
end
=> nil

the_proc = proc_with_enclosing_scope
NoMethodError: undefined method lamda' for main:Object from (irb):23:inproc_with_enclosing_scope’
from (irb):25

So… When the_proc gets assigned the … Value of the method
running… (?) What does it get assigned?

proc_with_enclosing_scope.class
=> Proc

And lastly… I know that “proc” exists, too. What is the difference /
what does it do?

lambda {} is nearly equivalent to Proc.new {}. See
http://ruby-doc.org/core/classes/Kernel.html#M005945 .

I thank you very much in advance for the enlightenment you will provide
:slight_smile:

Best,

Marnen Laibow-Koser
http://www.marnen.org
[email protected]

Marnen Laibow-Koser wrote:

Aldric G. wrote:

def proc_with_enclosing_scope
name = “Ruby”
lambda { puts name }
end

the_proc = proc_with_enclosing_scope
the_proc.call

name = “Java”
the_proc.call

why would changing the name outside the
method make a difference in the first place?

It doesn’t. Did you try the code? Both instances of the_proc.call
return “Ruby”. I assume the ‘name=“Java”’ line is just there to point
out that it’s not the same variable.

I did try the code. I was confused by what Dave T. was trying to
point out, it seemed obvious to me that the code would return Ruby both
times.

So… When the_proc gets assigned the … Value of the method
running… (?) What does it get assigned?

proc_with_enclosing_scope.class
=> Proc

And lastly… I know that “proc” exists, too. What is the difference /
what does it do?

lambda {} is nearly equivalent to Proc.new {}. See
http://ruby-doc.org/core/classes/Kernel.html#M005945 .

Alright… I had read that before and hadn’t made too much sense of it,
but maybe I’m just thinking too hard.
So… Proc and Lambda are … Pretty much the same thing, according to
Ruby.

So they really are “bits of code with its own environment” ?
When is that useful? Maybe I need to watch Dave T.’ presentation
again… :slight_smile:

Thanks, Marnen.

Aldric G. wrote:
[…]

So… Proc and Lambda are … Pretty much the same thing, according to
Ruby.

Not quite. There’s no such class as Lambda. Read what I said in my
first post again.

So they really are “bits of code with its own environment” ?
When is that useful? Maybe I need to watch Dave T.’ presentation
again… :slight_smile:

Closures are useful for certain things and in certain styles of
programming. In Rails they’re occasionally used for callbacks, and in
RSpec I often do things like
lambda {Car.drive}.should_not raise_error

See http://en.wikipedia.org/wiki/Closure_(computer_science) for more.

Thanks, Marnen.

You’re welcome!

Best,

Marnen Laibow-Koser
http://www.marnen.org
[email protected]

Marnen Laibow-Koser wrote:

Not quite. There’s no such class as Lambda. Read what I said in my
first post again.

I begin to understand. I’m reading this :
http://eli.thegreenplace.net/2006/04/18/understanding-ruby-blocks-procs-and-methods/
And it explains it as well.

In Rails they’re occasionally used for callbacks, and in
RSpec I often do things like
lambda {Car.drive}.should_not raise_error

See http://en.wikipedia.org/wiki/Closure_(computer_science) for more.

I’m reading that wiki page right now :wink:
About that RSpec example…

You are creating “code which calls Car.drive”, yes ? Why not just call
Car.drive ? That is the main bit of thinking I’m having issues with.

Zundra D. wrote:

I think what Dave was trying to illustrate with this example is that
even
though the method that you’re calling has gone out of scope that it
still
retains the value of the variable defined inside.

Whats fascinating about this simple example is the fact that the method
which is assigned to a remembers the context of everything defined
internally. Think about that for a second. In languages that do not
support closures the values of the properties defined are lost until the
next time the method is called, however closures not only remember the
values of their properties after the function goes out of scope but the
context in which they were originally defined. Its a pretty simple
concept
but a very powerful one at the same time.

Sounds like I was trying to overcomplicate it, when it’s just blindingly
obvious… Okay. I’ll try to play with that and see how far I can take
it. Thanks :slight_smile:

Aldric G. wrote:

Marnen Laibow-Koser wrote:

In Rails they’re occasionally used for callbacks, and in
RSpec I often do things like
lambda {Car.drive}.should_not raise_error

See http://en.wikipedia.org/wiki/Closure_(computer_science) for more.

I’m reading that wiki page right now :wink:
About that RSpec example…

You are creating “code which calls Car.drive”, yes ? Why not just call
Car.drive ? That is the main bit of thinking I’m having issues with.

Never mind!
I just found this : http://innig.net/software/ruby/closures-in-ruby.rb
Enlightening. Thanks again for your help, it makes it all easier to
read.

I’d actually like to know the answer to that one. What is the reason
for
enclosing the rspec test case in a lamda? Is it because you don’t want
the
exception actually raised in the test case but raised in another context
then observed?

Aldric G. wrote:

I don’t understand what Ruby is doing / what happens.
First question: the “name” variable is defined inside the method
proc_with_enclosing_scope, so why would changing the name outside the
method make a difference in the first place?

it doesn’t make a difference, it still prints 'Ruby"

And lastly… I know that “proc” exists, too. What is the difference /
what does it do?

Objects created with lambda don’t affect the flow of the application
outside of
the block when returning a value; Proc objects created with Proc.new, on
the
other hand, will exit their enclosing method when returning.

def procnew
new_proc = Proc.new { return “I got here…” }
new_proc.call
return “…but not here.”
end

def lambdaproc
new_proc = lambda { return “You get here…” }
new_proc.call
return “And I got here!”
end

Output

puts lambdaproc
=> And I got here!

puts procnew
=> I got here…

I thank you very much in advance for the enlightenment you will provide
:slight_smile:


Kind Regards,
Rajinder Y.

http://DevMentor.org

Do Good! - Share Freely, Enrich and Empower people to Transform their
lives.

def proc_with_enclosing_scope
name = “Ruby”
lambda { puts name }
end

This example relies on the fact that Ruby methods implicitly return the
value of the last expression evaluated. So perhaps you would find it
clearer as:

def proc_with_enclosing_scope
name = “Ruby”
return lambda { puts name }
end

or even:

def proc_with_enclosing_scope
name = “Ruby”
my_proc = lambda { puts name }
return my_proc
end

Now you can see that:

the_proc = proc_with_enclosing_scope
the_proc.call

just assigns the returned value (which happens to be a Proc object) to
the_proc, and then invokes the ‘call’ method on it.

This example isn’t much different to

return lambda { puts “Ruby” }

Where it gets more interesting is where you can modify the values inside
the closure:

def counter
count = 0
lambda { count += 1 }
end

c1 = counter
c2 = counter
puts c1.call
puts c1.call
puts c1.call
puts c2.call
puts c2.call
puts c1.call
puts c2.call

This demonstrates that the Proc objects c1 and c2 have their own
independent ‘count’ variables. They behave almost like instance
variables.

Regards,

Brian.

Zundra D. wrote:

I’d actually like to know the answer to that one. What is the reason
for
enclosing the rspec test case in a lamda? Is it because you don’t want
the
exception actually raised in the test case but raised in another context
then observed?

Well, for one thing, it’s just the way the RSpec API works. But it
makes sense: with lambda, the expression tested can be an arbitrary
block, not just a single statement:

lambda do
car = Car.new :make => “Toyota”, :color => :blue
car.options.add PowerSteeringUnit.new
car.drive
car.park
car.lock
end.should_not raise_error

Best,

Marnen Laibow-Koser
http://www.marnen.org
[email protected]

Hi,

Aldric G. wrote:

I just found this : http://innig.net/software/ruby/closures-in-ruby.rb
Enlightening. Thanks again for your help, it makes it all easier to read.

can someone please add this link to the mailing lists FAQ
(http://wiki.github.com/rdp/ruby_talk_faq).
I don’t have a github account or I would add it myself, but I think the
above document is a really great read for beginners.

Thank you!

Greetings,
Waldemar