Why no yield in 1.9.2 blocks?

Hi,

I searched in vain for the answer, but why doesn’t yield work inside
Ruby 192 blocks. The syntax allows you to pass the blocks as a &blk
param, but you have to call the block with blk.call. If you try to use
yield, you get a LocalJumpError:

ruby-1.9.2-p0 > l= lambda {|&blk| yield}
=> #<Proc:[email protected](irb):2 (lambda)>
ruby-1.9.2-p0 > l.call {puts 1}
LocalJumpError: no block given (yield)
from (irb):2:in block in irb_binding' from (irb):3:incall’
from (irb):3
from /Users/edh/.rvm/rubies/ruby-1.9.2-p0/bin/irb:17:in `’

But this works:

ruby-1.9.2-p0 > l= lambda {|&blk| blk.call}
=> #<Proc:[email protected](irb):4 (lambda)>
ruby-1.9.2-p0 > l.call {puts 1}
1
=> nil

At least it agrees with block_given?

ruby-1.9.2-p0 > l=lambda {|&blk| puts “block given” if block_given?;
puts “done”}
=> #<Proc:[email protected](irb):6 (lambda)>
ruby-1.9.2-p0 > l.call
done
=> nil
ruby-1.9.2-p0 > l.call {puts 1}
done
=> nil

I can live with block.call instead of yield, but no block_given?

Why would you want to pass a block to a block? Why not? so you can do
things like:

def meth(x, &block)
if block_given?
block.call(x) do |y|
puts "in meth " + y.to_s
end
end
end

ruby-1.9.2-p0 > meth(1) {|x, &blk| puts "in blok " + x.to_s; blk.call 2}
in blok 1
in meth 2

[Note, trying this with yield leads to a SyntaxError.]

Cheers,
Ed

Ed Howland


http://twitter.com/ed_howland

On Oct 22, 3:09pm, Ed Howland [email protected] wrote:

LocalJumpError: no block given (yield)
from (irb):2:in block in irb_binding' from (irb):3:incall’
from (irb):3
from /Users/edh/.rvm/rubies/ruby-1.9.2-p0/bin/irb:17:in `’

irb(main):002:0> p = proc{|&blk| yield}
=> #Proc:[email protected]:2(irb)
irb(main):003:0> p.call{puts 1}
LocalJumpError: no block given
from (irb):2
from (irb):3:in `call’
from (irb):3
from :0
irb(main):004:0> VERSION
=> “1.8.7”

On 22.10.2010 22:09, Ed Howland wrote:

I searched in vain for the answer, but why doesn’t yield work inside
Ruby 192 blocks. The syntax allows you to pass the blocks as a&blk
param, but you have to call the block with blk.call. If you try to use
yield, you get a LocalJumpError:

This isn’t something new in 1.9.2. There is no version of Ruby that I
am aware of that would allow this.

ruby-1.9.2-p0> meth(1) {|x,&blk| puts "in blok " + x.to_s; blk.call 2}
in blok 1
in meth 2

There are also other useful usecases for this, namely defining methods
with a block dynamically

in some class

define_method :foo do |x,y,&b|
puts “before”
yield # or b.call
puts “after”
end

Kind regards

robert

On Fri, Oct 22, 2010 at 3:09 PM, Ed Howland [email protected]
wrote:

Hi,

I searched in vain for the answer, but why doesn’t yield work inside
Ruby 192 blocks. The syntax allows you to pass the blocks as a &blk
param, but you have to call the block with blk.call. If you try to use
yield, you get a LocalJumpError:

I always figured it was because it was enclosing its environment, and
having
yield in the block and the environment could bet ambiguous.

def sort_proxy(collection)
collection.sort! do |a,b|
yield a , b # yield in a block
end
end

ary = [4,2,9,3,1]

sort_proxy ary do |a,b|
a <=> b
end

ary # => [1, 2, 3, 4, 9]

Josh C. wrote in post #956495:

I always figured it was because it was enclosing its environment, and
having
yield in the block and the environment could bet ambiguous.

Yes, I believe that’s the case. Consider:

def foo # <- block passed implicitly
bar do |&baz|
yield 123 # <- invokes the outer block
end
end

I think of ‘yield’ like ‘return’. ‘yield’ invokes the block passed in to
the enclosing method, and ‘return’ returns from the enclosing method.

This forum is not affiliated to the Ruby language, Ruby on Rails framework, nor any Ruby applications discussed here.

| Privacy Policy | Terms of Service | Remote Ruby Jobs