blocks, scope/context confusion

Discussion in 'Ruby' started by Corey, Jun 11, 2005.

  1. Corey

    Corey Guest

    I'm reading pages 358 & 359 in the pickaxe2 and having a tough time
    wrapping my mind around what exactly is going on.

    I've got a few simple questions that I'm hoping will help clarify my
    confusion.


    What's the difference between the two methods below?

    def meth1
    yield
    end

    def meth2(&b)
    b.call
    end


    What's the difference between the next two blocks? Does 'next' in any way
    make any sort of functional or subtle difference?

    blk = meth1 { 99 }
    puts blk

    blk = meth1 { next 99 }
    puts blk

    and...
    Why does the following cause an exception?

    meth { return 99 }


    As far as the above goes, I'm really struggling to understand how the
    scope and context works.

    "A return from a block whose original context is not longer valid raises
    an exception ( LocalJumpError )."

    In the following:

    meth { return 99 }

    _Where_/_What_ exactly _is_ the "original context", and how exactly does
    it become "no longer valid" with the 'return' statement?


    I've got some other questions, but I'm hoping that the above will help
    make some things 'click' for me.


    Many thanks!
    Corey, Jun 11, 2005
    #1
    1. Advertising

  2. Corey

    Corey Guest

    On Friday 10 June 2005 06:55 pm, Corey wrote:
    > meth { return 99 }
    >


    Quick correction/clarification -- in my post, the references/questions
    regarding that block, should have of course been to 'meth1'; not 'meth'.
    Corey, Jun 11, 2005
    #2
    1. Advertising

  3. Hi,

    In message "Re: blocks, scope/context confusion"
    on Sat, 11 Jun 2005 10:55:44 +0900, "Corey" <> writes:

    |Why does the following cause an exception?
    |
    |meth { return 99 }

    Because "return 99" at the toplevel causes an exception as well.
    Try

    def foo
    meth1 { return 99 }
    end
    p foo

    matz.
    Yukihiro Matsumoto, Jun 11, 2005
    #3
  4. Yukihiro Matsumoto wrote:

    >Because "return 99" at the toplevel causes an exception as well.
    >
    >

    Ah! Thanks (I was curious, too). That makes sense.

    >Try
    >
    > def foo
    > meth1 { return 99 }
    > end
    > p foo
    >
    >
    >

    Or, more to the point, try:

    def foo
    meth1 { return 99 }
    return 47
    end
    p foo

    Corey: Here's an article on closures (which are, as I understand it,
    what blocks are) that might help some:
    http://www.sidhe.org/~dan/blog/archives/000152.html

    Devin
    Devin Mullins, Jun 11, 2005
    #4
  5. Corey

    Guest

    On Jun 10, 2005, at 9:55 PM, Corey wrote:
    > I'm reading pages 358 & 359 in the pickaxe2 and having a tough time
    > wrapping my mind around what exactly is going on.


    I'm still climbing up the Ruby learning curve so I hope someone
    will gently correct my answers if I get them wrong :)

    In all these examples and my descriptions below I'm talking about what
    the book calls "raw procs" as opposed to "lambdas" which have slightly
    different semantics.

    > What's the difference between the two methods below?
    >
    > def meth1
    > yield
    > end
    >
    > def meth2(&b)
    > b.call
    > end


    There is no semantic difference. The first example is
    syntactic sugar for the second example. I believe there is
    a small "implementation" difference though. In the first example
    Ruby never converts the block associated with a call to meth1 to
    a full-blown instance of Proc. In the second example, the block is
    packaged up into a Proc object and then the method lookup for "call"
    results in the execution of the block. So the first example saves
    Ruby the trouble of allocating an object and then dispatching the
    method,
    and then the garbage collector eventually having to reclaim the
    discarded
    Proc.

    > What's the difference between the next two blocks? Does 'next' in
    > any way
    > make any sort of functional or subtle difference?
    >
    > blk = meth1 { 99 }
    > puts blk
    >
    > blk = meth1 { next 99 }
    > puts blk


    Also no semantic difference but that is just because the next statement
    happens to be the last expression in the block (from both a syntax and
    execution standpoint). Another way to say this is that the result of
    execution falling off the end of a block is for ruby to execute an
    implicit

    next val

    where 'val' is the value of the last expression in the block.

    > Why does the following cause an exception?
    >
    > meth { return 99 }


    Because in this particular example, the block is defined in the
    top-level context and at the top-level there is no active method
    and so there is nothing to "return" from. You get the same error
    if your entire ruby program was just:

    return 99

    When the block is defined within a method context you don't get the
    error:

    def foo
    meth1 { return 99 }
    return "impossible"
    end

    foo # 99

    Note that the 'return "impossible"' statement is never executed.

    > "A return from a block whose original context is not longer valid
    > raises
    > an exception ( LocalJumpError )."
    > In the following:
    >
    > meth { return 99 }
    >
    > _Where_/_What_ exactly _is_ the "original context", and how exactly
    > does
    > it become "no longer valid" with the 'return' statement?


    I think it is a bad example because the original context was *never*
    valid
    to start with. Here is a different example where the context exists
    and is
    valid at the time the block is defined but doesn't exist (and so is no
    longer valid) at the time the block is executed:

    def level1
    level2 { return "return from level1" }
    end

    def level2(&block)
    return block
    end

    bogus_block = level1
    bogus_block.call # ERROR


    Lambdas: The main difference with a block that is converted into a
    lambda
    is that a 'return' statement in a lambda is associated with the
    lambda itself
    and not the method that was active at the time associated block was
    defined.
    So within a lambda, 'return' has the same semantics as 'next' as
    described
    above.

    def level1
    level2 { return "return from lambda" }
    end

    def level2(&block)
    return (lambda &block)
    end

    valid_lambda = level1
    valid_lambda.call # "return from lambda"



    Gary Wright
    , Jun 11, 2005
    #5
  6. Corey

    Corey Guest

    On Friday 10 June 2005 07:14 pm, Yukihiro Matsumoto wrote:
    > on Sat, 11 Jun 2005 10:55:44 +0900, "Corey" <> writes:
    > |Why does the following cause an exception?
    > |
    > |meth { return 99 }
    >
    > Because "return 99" at the toplevel causes an exception as well.
    >


    Aha! That makes sense, thanks!
    Corey, Jun 11, 2005
    #6
  7. Corey

    Corey Guest

    On Friday 10 June 2005 07:26 pm, Devin Mullins wrote:
    > Corey: Here's an article on closures (which are, as I understand it,
    > what blocks are) that might help some:
    > http://www.sidhe.org/~dan/blog/archives/000152.html
    >


    Yes, that was _extremely_ helpful - thanks a ton!

    Does anyone know of any good articles/blogs/whatever that further describes
    and explains closures/blocks and their use in specific ruby terms/idioms?
    Corey, Jun 11, 2005
    #7
  8. Corey

    Corey Guest

    On Friday 10 June 2005 08:11 pm, wrote:
    > On Jun 10, 2005, at 9:55 PM, Corey wrote:
    > > I'm reading pages 358 & 359 in the pickaxe2 and having a tough time
    > > wrapping my mind around what exactly is going on.

    >
    > I'm still climbing up the Ruby learning curve so I hope someone
    > will gently correct my answers if I get them wrong :)

    <snip>


    Wow... that was a phenomenaly informative explanation for each of my
    questions!

    Many, many thanks - that was _extremely_ helpfull.


    Beers!

    Corey
    Corey, Jun 11, 2005
    #8
  9. --Apple-Mail-2-611845666
    Content-Transfer-Encoding: 7bit
    Content-Type: text/plain;
    charset=US-ASCII;
    delsp=yes;
    format=flowed

    On Jun 10, 2005, at 9:33 PM, Corey wrote:
    > Does anyone know of any good articles/blogs/whatever that further
    > describes
    > and explains closures/blocks and their use in specific ruby terms/
    > idioms?


    Not quite what you are looking for, but Jibber Jim has a good
    technical article on closures in Javascript at:
    http://jibbering.com/faq/faq_notes/closures.html


    --Apple-Mail-2-611845666--
    Gavin Kistner, Jun 11, 2005
    #9
  10. Corey

    Corey Guest

    On Saturday 11 June 2005 08:58 am, Gavin Kistner wrote:
    > Not quite what you are looking for, but Jibber Jim has a good
    > technical article on closures in Javascript at:
    > http://jibbering.com/faq/faq_notes/closures.html
    >


    This is good - thankyou for the link. It's one thing to know how closures
    work, then another thing to know when and where to use them!


    Cheers,

    Corey
    Corey, Jun 11, 2005
    #10
    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. John Cantley
    Replies:
    2
    Views:
    12,064
    ant177
    Dec 14, 2005
  2. Arjen
    Replies:
    3
    Views:
    436
    Scott Allen
    Feb 27, 2005
  3. Arved Sandstrom

    Blocks for scope control

    Arved Sandstrom, Jan 15, 2012, in forum: Java
    Replies:
    32
    Views:
    771
    Arne Vajhøj
    Feb 7, 2012
  4. matt
    Replies:
    1
    Views:
    254
    George Ogata
    Aug 6, 2004
  5. Steven Taylor
    Replies:
    9
    Views:
    247
    Brian Candler
    Apr 27, 2009
Loading...

Share This Page