Welcome to the Treehouse Community

Want to collaborate on code errors? Have bugs you need feedback on? Looking for an extra set of eyes on your latest project? Get support with fellow developers, designers, and programmers of all backgrounds and skill levels here with the Treehouse Community! While you're at it, check out some resources Treehouse students have shared here.

Looking to learn something new?

Treehouse offers a seven day free trial for new students. Get access to thousands of hours of content and join thousands of Treehouse students and alumni in the community today.

Start your free trial

Ruby

Ulfar Ellenarson
Ulfar Ellenarson
5,277 Points

the def each(&block) method

If somebody could explain to me how the &block in the def each(&block) is being called. I expected to see block.call somewhere in the enumerable.rb programme. I see that the any? method from enumerable runs on the block {|player| player.score > 80} for example but from my knowledge of procs and lambdas they need to be called. What happened to the call method?

Or does the enumerable method any? do the block.call on the Proc(&block)? In other words do the enumerable methods in enumerable.rb programme run the call method block.call when using the enumerable methods like any? or find_all.

6 Answers

Ulfar Ellenarson
Ulfar Ellenarson
5,277 Points

I think I solved my own question. What happens is that the class Game has Enumerable and by defining each to take a block and run players.each(&block) is that the instance or (object) game1 = Game.new can have any of the methods ie. any? or find run on the block defined in the def each(&block) method. So for example game1.any?{|player| player.score > 80} what happens is that the method def each(&block) in the Game class runs on the block {|player| player.score > 80} in other words def each({|player| player.score > 80}, players.each{|player| player.score > 80}, end and the any? method from Enumerables can then be used. Example to that shed more light on this came from http://awaxman11.github.io/blog/2013/08/05/what-is-the-difference-between-a-block/ [1] pry(main)> p = Proc.new {|x| puts x * 2} => #<Proc:0xb03fe34@(pry):1> [2] pry(main)> [1, 2, 3].each(&p) 2 4 6 => [1, 2, 3]

Awesome! :thumbsup:

So this is a example of passing in a block into a method:

def run_block(&block)
    yield block  # Call the block
end

run_block { puts "Hello!" }

Hope that explains it! :dizzy:

Ulfar Ellenarson
Ulfar Ellenarson
5,277 Points

Thank you Alexander. Unfortunately that does not explain what I enquiring about. The method I am discussing comes from the programme enumerable.rb and as you can see in the code below the method def each(&block) is not using a yield or block.call and that is what I am trying to understand.

class Player
  include Comparable
  attr_accessor :name, :score

  def <=>(other_player)
    score <=> other_player.score
  end

  def initialize(name, score)
    @name, @score = name, score
  end
end

class Game
  include Enumerable

  attr_accessor :players

  def each(&block)                      
    players.each(&block)       
  end

  def initialize
    @players = []
  end

  def add_player(player)
    players.push(player)
  end

  def score
    score = 0
    players.each do |player|
      score += player.score
    end
    score
  end

        def name
                players.each do |player|
                        players[] << player.name
                end
                players
        end
end

player1 = Player.new("Jason", 100)
player2 = Player.new("Kenneth", 80)
player3 = Player.new("Nick", 95)
player4 = Player.new("Craig", 20)

game1 = Game.new
game1.add_player(player1)
game1.add_player(player2)

game2 = Game.new
game2.add_player(player3)
game2.add_player(player4)

puts game1.inspect

puts game1.any?{|player| player.name == "Nick"}
puts game1.any?{|player| player.name == "Jason"}
puts game1.any?{|player| player.score > 80}

players = game1.find{|player| player.score > 80}
puts "Players with a score > 80", players.inspect

[MOD: edited code block. sh]

Sorry but can you please style the code so that I can read it?

Ulfar Ellenarson
Ulfar Ellenarson
5,277 Points

Sure. I was specifically refering to this method.

def each(&block)                      
    players.each(&block)       
  end

[MOD: edited code block. sh]

Oh this is like saying "for each element in players, run &block"

Hope that makes sense! :dizzy:

Oh this is like saying "for each element in players, run &block"

Hope that makes sense! :dizzy:

Ulfar Ellenarson
Ulfar Ellenarson
5,277 Points

I understand it in that context but the &block is a proc and how is it being called. You normally need to run call method on proc to get a return on the proc object.

Should I understand that &block remains a block and not a proc?

I checked and the &block returns Proc

def each(&block)
    players.each(&block)
    puts block.class   # returns Proc
end

[MOD: edited code block. sh]

Hmmm... I actually, I don't know much about this XD

Ulfar Ellenarson
Ulfar Ellenarson
5,277 Points

Yes. This is something I am trying to understand as I have studied blocks, lambda and procs but I don't know if the enumerable class methods are able to implicitly call methods on procs. I hope somebody can shed light on this.