[lnkForumImage]
TotalShareware - Download Free Software

Confronta i prezzi di migliaia di prodotti.
Asp Forum
 Home | Login | Register | Search 


 

Forums >

comp.lang.ruby

blocks, scope/context confusion

Corey

6/11/2005 1:56:00 AM


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!


9 Answers

Corey

6/11/2005 1:59:00 AM

0

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'.




Yukihiro Matsumoto

6/11/2005 2:15:00 AM

0

Hi,

In message "Re: blocks, scope/context confusion"
on Sat, 11 Jun 2005 10:55:44 +0900, "Corey" <corey_s@qwest.net> 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.


Devin Mullins

6/11/2005 2:26:00 AM

0

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/0...

Devin



Gary Wright

6/11/2005 3:11:00 AM

0


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



Corey

6/11/2005 3:31:00 AM

0

On Friday 10 June 2005 07:14 pm, Yukihiro Matsumoto wrote:
> on Sat, 11 Jun 2005 10:55:44 +0900, "Corey" <corey_s@qwest.net> 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

6/11/2005 3:34:00 AM

0

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/0...
>

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

6/11/2005 3:38:00 AM

0

On Friday 10 June 2005 08:11 pm, gwtmp01@mac.com 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


Gavin Kistner

6/11/2005 3:58:00 PM

0

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/clo...

Corey

6/11/2005 6:51:00 PM

0

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/clo...
>

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