Objects, Collections, and Blocks

Darren Day

Standard Types

Regular Expressions


puts "test" =~ /e(.)/1
puts "captured after e: #{$1}"captured after e: s
three_digits = Regexp.new('(\d\d\d)') match_data = three_digits.match("alpha 557 beta") puts "found #{match_data[1]}" unless match_data.nil? found 557

Arrays


words=["this","that","these","those"] puts words[2] puts words[4] puts words[-1] these nil those

Changing Arrays


words[0]="more" puts words ["more","that","these","those"]
words[4]=-32 ["more","that","these","those",-32]
words.delete(-32)["more","that","these","those"]

Arrays are Objects


puts words.length puts "found these!" if words.include?("these") words.each { |item| print "#{item} " } 4 found these! more that these those Wait...what is that each { } stuff?

Arrays, Blocks, and Iteration

By passing a block of code to certain array methods, you can specify code to run for each iterated item.
words.find_all { |item| item.length == 5 }["these","those"] words.partition do |item| item.length % 2 == 0 end
[["more", "that"], ["these", "those"]]
words.collect { |item| item.reverse } ["erom", "taht", "eseht", "esoht"] We'll come back to blocks in a minute...

Hashes


info = { 'name' => 'Darren', 'age' => 32, 'occupation' => 'Coder' } info['name'] 'Darren' info['hometown'] 'nil' info['hometown']='Whitesburg, Kentucky' info['hometown'] 'Whitesburg, Kentucky'

Hashes are Objects


info.length 4 info.values ["Coder", "Darren", 32, 'Whitesburg, Kentucky'] info.has_key?('hometown') true info.each { |k,v| print "#{k}:#{v} " } name:Darren occupation:Coder age:32 hometown:Whitesburg, Kentucky There's that each { } again...

Hashes, Blocks, and Iteration


info.find_all { |k,v| k.length % 2 != 0} [["age", 32]]
groups = Hash.new do |h,k| h[k] = Array.new end puts groups['people'].inspect groups['places'].push("Whitesburg, Kentucky") groups['places'] << "Louisville, Kentucky" # << alias for .push puts groups['places'].inspect [] ['Whitesburg, Kentucky', 'Louisville, Kentucky']

What are Blocks?

Blocks and Iteration


total = 0 donors.each do |donor| puts donor.name total += donor.donation end puts "Total donation: $#{total}" Chuck Fouts Anne McWilliams Al Alexander Total donation: $315.15

Blocks and Transactions


File.open("foo.txt","w") do |foo| foo.puts("Ahh...no worries") foo.puts("The open method will worry about") foo.puts("closing the file") end

With and Without Blocks

Blocks hide the mechanics and reveal the specifics. animals = ['cat','dog','cow','duck','chicken'] c_zoo = Array.new for animal in animals c_zoo.push(animal) if animal =~ /^c/ end puts c_zoo.inspect ['cat','cow','chicken']
puts animals.find_all { |animal| animal =~ /^c/ }.inspect ['cat',cow','chicken']

Don't Repeat Yourself

Blocks from Both Sides

It's easy to write code that accepts blocks...just yield to them...

def twice_over(value) yield value yield value end twice_over("boo") { |value| puts value } boo boo

Blocks Can Access Context

Blocks inherit the variables from the current context.

def twice_over(value) yield value yield value end total=3 twice_over(15) do |value| total += value end puts total 33

Let's See some Demos

www.flickr.com/photos/kubina/60259105/