Skip to content

Instantly share code, notes, and snippets.

@eprothro
Last active August 29, 2015 14:16
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save eprothro/383829fc07713e97cf80 to your computer and use it in GitHub Desktop.
Save eprothro/383829fc07713e97cf80 to your computer and use it in GitHub Desktop.
yield in Ruby | Primer

Yield doesn't return, a method may yield to a passed block multiple times

class Test
  def some_method
    yield 'foo'
    yield 'bar'
  end
end
Test.new.some_method{|a| puts a}
foo
bar
=> nil

Yielding multiple arguments to a block is possible

class Test  
  def some_method
    yield 'foo', 'bar'
    yield 'baz', 'bat'
  end
end
Test.new.some_method{|a, b| puts "#{a} + #{b}"}
foo + bar
baz + bat
=> nil

Enumerable works only by providing a method named each that yields to everything expected

class Test  
  include Enumerable
  def each
    yield 'foo', 'bar'
    yield 'baz', 'bat'
  end
end
Test.new.map{|a, b| a + ': ' + b}
=> ["foo: bar", "baz: bat"]

And now for a more realistic application

class MoreRealisticTest
  attr_reader :collection1, :collection2

  def initialize
    @collection_a = ['foo', 'bat']
    @collection_b = {
                    'foo' => 'bar',
                    'bat' => 'baz'
                   }
  end
  def my_pairs
    @collection_a.each do | a |
      yield a, @collection_b[a]
    end
  end
end
MoreRealisticTest.new.my_pairs do | a, b |
  puts "#{a}: #{b}"
end
foo: bar
bat: baz
=> ["foo", "bat"]

Note that at this point, my_pairs returning an Enumerator is probably more appropriate.

One more useful thing to know - yield returns the result from the block

class Test
  def my_map
    my_array = []
    my_array << yield(1)
    my_array << yield(2)
  end
end
Test.new.my_map{|x| x*x}
=> [1, 4]
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment