mark
mark

Reputation: 5070

How to wrap a method that yields in Ruby 1.9

I have a method that prints out a numbered list, yielding to a code block to print a prefix.

arr = %w(a b c)

def print_lines(array)
  array.each_with_index do |item, index|
    prefix = yield index
    puts "#{prefix} #{item}"
  end
end

print_lines(arr) do |index|
  "(#{index})"
end

This produces the following output:

(0) a
(1) b
(2) c

Now I want to wrap print_lines in another method and call it.

def print_lines_wrapped(array)
  puts 'print_lines_wrapped'
  print_lines(array)
end

print_lines_wrapped(arr) do |index|
  "(#{index})"
end

However, this gives me a LocalJumpError

test_yield.rb:5:in `block in print_lines': no block given (yield) (LocalJumpError)
  from test_yield.rb:4:in `each'
  from test_yield.rb:4:in `each_with_index'
  from test_yield.rb:4:in `print_lines'
  from test_yield.rb:16:in `print_lines_wrapped'
  from test_yield.rb:19:in `<main>'

Why do I get a LocalJumpError?

How can I implement print_lines_wrapped such that I can call it like this:

print_lines_wrapped(arr) do |index|
  "(#{index})"
end

and get the following output:

print_lines_wrapped
(0) a
(1) b
(2) c

?

Upvotes: 3

Views: 732

Answers (1)

ichigolas
ichigolas

Reputation: 7725

Your wrapper method also has to accept a block and pass it to the wrapped method. There is no implicit passing of the block:

def print_lines_wrapped(array, &block)
  puts 'print_lines_wrapped'
  print_lines(array, &block)
end

Example:

def asdf(&block) puts yield(2) end
def qwer(&block)
  puts "I am going to call asdf"
  asdf &block
end

asdf { |x| x * 3 }
6
=> nil
qwer { |x| x * 5 }
I am going to call asdf
10
=> nil

The & operator converts its operand into a block if possible

 qwer &Proc.new { |x| x * 2 }
 I am going to call asdf
 4

Upvotes: 2

Related Questions