2

How should one proceed if one wants to yield to the block of the caller's caller? I came up with the following:

def method1(param)
  method2(param) { |x| yield x if block_given? }
end

def method2(param)
  yield(param) if block_given?   # Can I yield from here
end

method1("String") { |x| puts x } # to here in a more elegant way?
N.N.
  • 8,336
  • 12
  • 54
  • 94

2 Answers2

2

Just pass the block explicitly

def method1(param, &block)
  method2(param, &block)
end

def method2(param)
  yield param if block_given?
end

method1("String") { |x| puts x } # >> String
Sergio Tulentsev
  • 226,338
  • 43
  • 373
  • 367
  • Personally I don't dislike the explicit block, but AFAIK orthodoxy says that `method2` should drop the argument `&block` and make a `yield if block_given?` – tokland Jan 10 '13 at 15:16
  • 1
    @tokland: agreed. Updated the post. – Sergio Tulentsev Jan 10 '13 at 15:19
  • @tokland Why is that more orthodox? The answer would be better if it included a motivation for why this particular formulation is good. – N.N. Jan 10 '13 at 18:52
  • @N.N. I don't have numbers to show, but check code by experienced Ruby coders and you'll see that it's a common practice. The rationale may be like this: 1) `yield` is more idiomatic than `block.call` (that's why the syntantic sugar exists in the first place). 2) If `block` is not used as such it makes no sense to pass it as argument (all Ruby methods can take a block, whether or not there is a block argument). Suprised that https://github.com/bbatsov/ruby-style-guide does not discuss this matter. Check also http://stackoverflow.com/questions/1410160/ruby-proccall-vs-yield – tokland Jan 10 '13 at 19:23
2

One way is to not use yield in the first method:

def method1(param, &block)
  method2(param, &block)
end

def method2 param
  yield param if block_given?
end

The unary ampersand represents the "block slot" in the method's parameter list. When you pass a block, you can access the block that was passed by putting the & right before the final parameter name. It can be passed around to other methods in the same way.

You can see lots of details about & here: http://ablogaboutcode.com/2012/01/04/the-ampersand-operator-in-ruby/

robbrit
  • 17,560
  • 4
  • 48
  • 68