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?

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]

Hi,

···

In message “break in yield/block” on 03/11/20, matt mhm26@drexel.edu writes:

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.

matz@ruby-lang.org (Yukihiro Matsumoto) wrote in message news:1069269880.596357.859.nullmailer@picachu.netlab.jp

Hi,

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!

···

In message “break in yield/block” > on 03/11/20, matt mhm26@drexel.edu writes:

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

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

Hi,

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

In message “Re: break in yield/block” on 03/11/20, matt mhm26@drexel.edu writes:

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’ –

matz@ruby-lang.org (Yukihiro Matsumoto) wrote in message news:1069395225.856100.31032.nullmailer@picachu.netlab.jp

Hi,

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?

···

In message “Re: break in yield/block” > on 03/11/20, matt mhm26@drexel.edu writes:

Hi,

···

In message “Re: break in yield/block” on 03/11/22, matt mhm26@drexel.edu writes:

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.