break in yield/block

M

matt

Is there any reason that break acts differently in a block passed to a
method depending on whether yield is used?

Code:
def meow(doyield, &block)
puts "in meow #{doyield}"
if doyield then yield else block[] end
puts "leaving meow"
end

b = proc {
puts "in proc"
break
puts "leaving proc"
}

meow(true, &b)
puts
meow(false, &b)

[run]
bash-2.05$ ruby test.rb
in meow true
in proc

in meow false
in proc
leaving meow
bash-2.05$ ruby --version
ruby 1.6.7 (2002-03-01) [sparc-solaris2.7]
[/run]

[run]
[matt@linux1 matt]$ ruby test.rb
in meow true
in proc

in meow false
in proc
leaving meow
[matt@linux1 matt]$ ruby --version
ruby 1.8.0 (2003-08-04) [i586-linux]
[/run]
 
Y

Yukihiro Matsumoto

Hi,

In message "break in yield/block"

|Is there any reason that break acts differently in a block passed to a
|method depending on whether yield is used?

Because they are different. "break" in a block terminates a method
that the block is attached to. In your example, it is "meow" when
doyield, and "[]" when not.

I'm not sure what you think they should be.

matz.
 
M

matt

Hi,

In message "break in yield/block"

|Is there any reason that break acts differently in a block passed to a
|method depending on whether yield is used?

Because they are different. "break" in a block terminates a method
that the block is attached to. In your example, it is "meow" when
doyield, and "[]" when not.

I'm not sure what you think they should be.

matz.

I figured that was why break was terminating in #[] - but why not have
yield act as a `method' in this sense? My guess is that in this
respect, they should be the same. Should I really be writing my
blocks to work a certain way depending on whether the implementor
decided to use yield or [], or whether I'm doing something like
list_of_methods_args.each {|meth, *args| meth.call(args,
&special_magic)}
(this is assuming that there are stand alone methods attached to
instances - I heard there are in 1.8.x - otherwise, rework code yadda
yadda)

- then I have to worry about how blocks are used in each one if
special_magic uses break - what if the list was made dynamically from
reflection, etc? Granted, I generally don't use break - especially in
lambdas - but its still something I didn't expect.

~Me!
 
T

ts

m> - then I have to worry about how blocks are used in each one if
m> special_magic uses break - what if the list was made dynamically from
m> reflection, etc? Granted, I generally don't use break - especially in
m> lambdas - but its still something I didn't expect.

well, the problem is that you have written something strange.

Your first example was

def meow
yield
end

meow do
puts "in block"
break
puts "leaving block"
end

Your second example was

p = proc do
puts "in proc"
break
puts "leaving proc"
end

def meow(block)
block[]
end

meow(p)



Guy Decoux
 
M

matt

well, the problem is that you have written something strange.
Your first example was

def meow
yield
end

meow do
puts "in block"
break
puts "leaving block"
end

Your second example was

p = proc do
puts "in proc"
break
puts "leaving proc"
end

def meow(block)
block[]
end

meow(p)

The first example is the same as
def meow
yield
end

meow {
puts "in proc"
break
puts "leaving proc"
}

The second example is more akin to

def meow(&block)
block[]
end

meow {
puts "in proc"
break
puts "leaving proc"
}

than what you gave. Note that the only thing that changed is the
definition of meow - not the invocation.

Also - for my list example, I of course meant
list_of_methods_args.each {|meth, *args|
meth.call(*args, &special_magic)
}
as opposed to the original
list_of_methods_args.each {|meth, *args|
meth.call(args, &special_magic)
}
-- change is `meth.call(args' to meth.call(*args' --
 
Y

Yukihiro Matsumoto

Hi,

In message "Re: break in yield/block"

|I figured that was why break was terminating in #[] - but why not have
|yield act as a `method' in this sense? My guess is that in this
|respect, they should be the same.

They cannot be same. I would surprise if calling Proc#[] terminates
meow(). But I prepared the way to make meow behave as you expect:

def meow(doyield, &block)
puts "in meow #{doyield}"
if doyield
yield
else
block[]
end
puts "leaving meow"
rescue LocalJumpError
return
end

b = Proc.new {
puts "in proc"
break
puts "leaving proc"
}

meow(true, &b)
puts
meow(false, &b)

Tip: do not use "proc" nor "lambda" when you want objectified Block.

matz.
 
M

matt

Hi,

In message "Re: break in yield/block"

|I figured that was why break was terminating in #[] - but why not have
|yield act as a `method' in this sense? My guess is that in this
|respect, they should be the same.

They cannot be same. I would surprise if calling Proc#[] terminates
meow(). But I prepared the way to make meow behave as you expect:

I was actually desiring the other way - that break from yield act like
break from Proc#[].

def meow(doyield, &block)
puts "in meow #{doyield}"
if doyield
yield
else
block[]
end
puts "leaving meow"
rescue LocalJumpError
return
end

b = Proc.new {
puts "in proc"
break
puts "leaving proc"
}

meow(true, &b)
puts
meow(false, &b)

Tip: do not use "proc" nor "lambda" when you want objectified Block.

matz.

Is there a reason that Proc#[] is different wrt this depending on
whether or not proc/lambda was used, and are there any other
differences?

I still don't see why the break works the way it does (well, I can
understand the reasoning) - but if I break inside a block, then I want
that block to terminate, not the method.

My current plans are to just do something like this
method_invoke(*args) {|*block_args|
callcc {|block_break|
code - yadda yadda yadda
block_break.call if want break / return from block
other code...
}
}

Any better ideas?
 
Y

Yukihiro Matsumoto

Hi,

In message "Re: break in yield/block"

|I still don't see why the break works the way it does (well, I can
|understand the reasoning) - but if I break inside a block, then I want
|that block to terminate, not the method.

That's how break is defined to work. Use "next" instead to terminates
block execution.

matz.
 

Ask a Question

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

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,774
Messages
2,569,599
Members
45,177
Latest member
OrderGlucea
Top