Skip to content

Instantly share code, notes, and snippets.

@vanderhoop
Last active August 29, 2015 14:11
Show Gist options
  • Select an option

  • Save vanderhoop/814d0f00e8b8a9997058 to your computer and use it in GitHub Desktop.

Select an option

Save vanderhoop/814d0f00e8b8a9997058 to your computer and use it in GitHub Desktop.

Intro to Blocks & Enumeration

Learning Objectives

  • Students should be able to:
    • Explain what a block is
    • Compare and contrast blocks and methods
    • User .each to iterate through arrays of unknown size

Part 1: Blocks

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:

  1. In the code above, what is .times ?
  • a method called on the Fixnum value 5
  1. What is {?
    • this tells the ruby interpreter, "Hey, a block has begun."
  2. 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
  3. What is } ?
    • this tells the ruby interpreter, "the block has ended."

Alternate Syntax

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."
end

As a general rule, you use the bracket syntax for one-liners and the do/end syntax for multi-line blocks.

Blocks with Arguments

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.

  1. What is ages ?
  • an array holding three Fixnum values
  1. What is .each ?
  • a method you can call on Arrays and Hashes. It expects you to pass it a block.
  1. What is { ?
  • the beginning of the block
  1. What is x between the two pipes | |on line 3?
  • x is a block argument. It tells Ruby that within the block, you want to refer to the each value in the array as x
  1. What is puts x?
  • the inner block code that will execute
  1. What value does x represent the first time the code block is executed?
  • 27
  1. What value does x represent the third and final time the code block is executed?
  • 33
  1. What is the return value of .each ?
  • the array that each was called upon

Iterating Through An Array Holding Data Structures

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|

end

Dissection

  1. What value will record refer to the first time the code block is executed?
  • the Hash { :year => 2013, :title => "Yeezus" }
  1. What value will record refer 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
end

Scope

Blocks 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
end

Why 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.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment