- Students should be able to:
- Explain what a block is
- Compare and contrast blocks and methods
- User
.eachto iterate through arrays of unknown size
Blocks are nameless chunks of code that we pass to methods, often for repeated execution. Here's a simple example.
5.times { puts "Blocks are nameless chunks of code that we pass to methods." }
####### ^ block begins here ^ block ends here Dissection:
- In the code above, what is
.times?
- a method called on the Fixnum value
5
- What is
{?- this tells the ruby interpreter, "Hey, a block has begun."
- What is
puts "Blocks are nameless chunks of code that we pass to methods"?- the content of the block, i.e. the code that will run 5 times
- What is
}?- this tells the ruby interpreter, "the block has ended."
The block above uses the single-line block syntax. Blocks can also be written using the do/end syntax.
5.times do
puts "Blocks are nameless chunks of code that we pass to methods, often for repeated execution."
endAs a general rule, you use the bracket syntax for one-liners and the do/end syntax for multi-line blocks.
Okay, so we've established that blocks get passed to methods, often for repeated execution. This makes them perfect for working with arrays, because we often want to execute the same process for each value.
Example:
ages = [27, 31, 33]
# prints *each* value in the ages array to the console
ages.each { |x| puts x }Dissection:
Leave the code on the projector, have the students pair up with a new partner and together answer the following questions.
- What is
ages?
- an array holding three Fixnum values
- What is
.each?
- a method you can call on Arrays and Hashes. It expects you to pass it a block.
- What is
{?
- the beginning of the block
- What is
xbetween the two pipes| |on line 3?
xis a block argument. It tells Ruby that within the block, you want to refer to the each value in the array asx
- What is
puts x?
- the inner block code that will execute
- What value does
xrepresent the first time the code block is executed?
- 27
- What value does
xrepresent the third and final time the code block is executed?
- 33
- What is the return value of
.each?
- the array that each was called upon
Great, so we've begun iterating through arrays with .each. This is a powerful tool when our arrays are filled with simple datatypes like strings, and becomes incredibly powerful when our arrays are populated with complex data structures, i.e. hashes. Create a file called kanye_records.rb.
kanye_records = [
{ :year => 2013, :title => "Yeezus" },
{ :year => 2011, :title => "Watch the Throne" },
{ :year => 2010, :title => "My Beautiful Dark Twisted Fantasy" },
{ :year => 2008, :title => "808s and Heartbreak" },
{ :year => 2007, :title => "Graduation" },
{ :year => 2005, :title => "Late Registration" },
{ :year => 2004, :title => "The College Dropout" }
]Let's run through some examples using the records of Kanye West
# what does iterating through kanye_records require?
kanye_records.each do |record|
endDissection
- What value will
recordrefer to the first time the code block is executed?
- the Hash
{ :year => 2013, :title => "Yeezus" }
- What value will
recordrefer to the last time the code block is executed?
- the Hash
{ :year => 2004, :title => "The College Dropout" }
Let's print some stuff about Kanye.
kanye_records.each do |record|
puts "Kanye came out with #{record[:title]} in #{record[:year]}."
end
puts "Since 2010, Kanye has come out with these records:"
kanye_records.each do |record|
if record[:year] > 2009
puts record[:title]
end
endBlocks are like cars with ridiculously tinted windows. When you're in them, you can see the outside world, but the outside world can't see you.
Here's an example
# w02/d01/Classwork/kanye_records.rb
# let's imagine that we want to build an array of only Kanye's early, pre-autotune stuff
pre_autotune_records = []
kanye_records.each do |record|
if record[:year] < 2008
pre_autotune_records.push(record)
end
end
# now let's imagine we want a collection of only the more recent, totally egotistical records, like MBDTF, WTT, and Yeezus
egotistical_records = []
kanye_records.each do |record|
if record[:year] >= 2010
egotistical_records << record
end
endWhy do we have to create the waiting arrays outside of the block? Because if we opened the new array in the block, the variable egotistical_records would be reassigned to an empty array each time the block was executed.