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 trialUlfar Ellenarson
5,277 Pointsthe 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
5,277 PointsI 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]
Alexander Davison
65,469 PointsSo 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!
Ulfar Ellenarson
5,277 PointsThank 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]
Alexander Davison
65,469 PointsSorry but can you please style the code so that I can read it?
Ulfar Ellenarson
5,277 PointsSure. I was specifically refering to this method.
def each(&block)
players.each(&block)
end
[MOD: edited code block. sh]
Alexander Davison
65,469 PointsOh this is like saying "for each element in players, run &block"
Hope that makes sense!
Alexander Davison
65,469 PointsOh this is like saying "for each element in players, run &block"
Hope that makes sense!
Ulfar Ellenarson
5,277 PointsI 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]
Alexander Davison
65,469 PointsHmmm... I actually, I don't know much about this XD
Ulfar Ellenarson
5,277 PointsYes. 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.
Alexander Davison
65,469 PointsAlexander Davison
65,469 PointsAwesome!