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: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://twitter.com/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>'

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
irb(main):004:0> VERSION
=> "1.8.7"

···

On Oct 22, 3:09 pm, Ed Howland <ed.howl...@gmail.com> wrote:
        from :0

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

···

On 22.10.2010 22:09, Ed Howland wrote:

--
remember.guy do |as, often| as.you_can - without end
http://blog.rubybestpractices.com/

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]

···

On Fri, Oct 22, 2010 at 3:09 PM, Ed Howland <ed.howland@gmail.com> 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:

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.

···

--
Posted via http://www.ruby-forum.com/\.