Closures / lambda question

Discussion in 'Ruby' started by Aldric Giacomoni, Oct 28, 2009.

  1. This is something I don't understand, and did not understand when I
    studied LISP. I just watched Dave Thomas' 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:in `proc_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
    :)
    --
    Posted via http://www.ruby-forum.com/.
    Aldric Giacomoni, Oct 28, 2009
    #1
    1. Advertising

  2. Aldric Giacomoni wrote:
    > This is something I don't understand, and did not understand when I
    > studied LISP. I just watched Dave Thomas' 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:in `proc_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
    > :)


    Best,
    --
    Marnen Laibow-Koser
    http://www.marnen.org

    --
    Posted via http://www.ruby-forum.com/.
    Marnen Laibow-Koser, Oct 28, 2009
    #2
    1. Advertising

  3. [Note: parts of this message were removed to make it a legal post.]

    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.

    On Tue, Oct 27, 2009 at 11:24 PM, Aldric Giacomoni <>wrote:

    > This is something I don't understand, and did not understand when I
    > studied LISP. I just watched Dave Thomas' 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:in `proc_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
    > :)
    > --
    > Posted via http://www.ruby-forum.com/.
    >
    >
    Zundra Daniel, Oct 28, 2009
    #3
  4. Marnen Laibow-Koser wrote:
    > Aldric Giacomoni 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 Thomas 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 Thomas' presentation
    again.. :)

    Thanks, Marnen.
    --
    Posted via http://www.ruby-forum.com/.
    Aldric Giacomoni, Oct 28, 2009
    #4
  5. Zundra Daniel 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 :)
    --
    Posted via http://www.ruby-forum.com/.
    Aldric Giacomoni, Oct 28, 2009
    #5
  6. Aldric Giacomoni 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 Thomas' presentation
    > again.. :)


    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

    --
    Posted via http://www.ruby-forum.com/.
    Marnen Laibow-Koser, Oct 28, 2009
    #6
  7. 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 ;-)
    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.
    --
    Posted via http://www.ruby-forum.com/.
    Aldric Giacomoni, Oct 28, 2009
    #7
  8. Aldric Giacomoni 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 ;-)
    > 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.
    --
    Posted via http://www.ruby-forum.com/.
    Aldric Giacomoni, Oct 28, 2009
    #8
  9. [Note: parts of this message were removed to make it a legal post.]

    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?

    On Wed, Oct 28, 2009 at 12:36 AM, Aldric Giacomoni <>wrote:

    > Aldric Giacomoni 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)<http://en.wikipedia.org/wiki/Closure_%28computer_science%29>for more.

    > >
    > > I'm reading that wiki page right now ;-)
    > > 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.
    > --
    > Posted via http://www.ruby-forum.com/.
    >
    >
    Zundra Daniel, Oct 28, 2009
    #9
  10. Aldric Giacomoni 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
    > :)



    --
    Kind Regards,
    Rajinder Yadav

    http://DevMentor.org

    Do Good! - Share Freely, Enrich and Empower people to Transform their lives.
    Rajinder Yadav, Oct 28, 2009
    #10
  11. > 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.
    --
    Posted via http://www.ruby-forum.com/.
    Brian Candler, Oct 28, 2009
    #11
  12. Zundra Daniel 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

    --
    Posted via http://www.ruby-forum.com/.
    Marnen Laibow-Koser, Oct 28, 2009
    #12
  13. Waldemar Dick, Oct 30, 2009
    #13
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Roman Suzi
    Replies:
    13
    Views:
    595
    Bengt Richter
    Jan 7, 2005
  2. Louis Steinberg

    problem with lambda / closures

    Louis Steinberg, Nov 30, 2009, in forum: Python
    Replies:
    1
    Views:
    245
    Marco Mariani
    Nov 30, 2009
  3. Terry Reedy

    Re: problem with lambda / closures

    Terry Reedy, Nov 30, 2009, in forum: Python
    Replies:
    2
    Views:
    277
    Terry Reedy
    Dec 1, 2009
  4. Steve Dogers

    lambda vs non-lambda proc

    Steve Dogers, Mar 30, 2009, in forum: Ruby
    Replies:
    1
    Views:
    160
    Sean O'Halpin
    Mar 30, 2009
  5. Stu
    Replies:
    31
    Views:
    358
    Steve Klabnik
    Apr 27, 2011
Loading...

Share This Page