Why no yield in 1.9.2 blocks?

E

Ed Howland

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:0x000001009d4ad0@(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:in `call'
from (irb):3
from /Users/edh/.rvm/rubies/ruby-1.9.2-p0/bin/irb:17:in `<main>'

But this works:

ruby-1.9.2-p0 > l= lambda {|&blk| blk.call}
=> #<Proc:0x000001009dc910@(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:0x00000101825f30@(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://greenprogrammer.wordpress.com
http://twitter.com/ed_howland
 
W

w_a_x_man

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:0x000001009d4ad0@(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:in `call'
        from (irb):3
        from /Users/edh/.rvm/rubies/ruby-1.9.2-p0/bin/irb:17:in `<main>'

irb(main):002:0> p = proc{|&blk| yield}
=> #<Proc:0x02833540@(irb):2>
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"
 
R

Robert Klemme

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

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
 
J

Josh Cheek

[Note: parts of this message were removed to make it a legal post.]

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]
 
B

Brian Candler

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

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,769
Messages
2,569,581
Members
45,055
Latest member
SlimSparkKetoACVReview

Latest Threads

Top