Objects, Collections, and Blocks
Darren Day
Standard Types
- Numbers (3, 15.5, 0x0a)
- Strings ('hello' "2+2=#{4}" %.Darren's got "quotes".)
- Regular Expressions (/\d{3}/)
- Arrays ( [1,2,3] )
- Hashes ( {'name'=>'Ed', 'age'=>32} )
- Ranges ( 1..10 "a"..."z" )
- Symbols ( :symbol )
Regular Expressions
- Very Perl-ish; even includes magic variables like $1...$9.
- Provided by an object, Regexp
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
- Numerically indexed collections of objects
- 0-based indexing
- Exceeding the length returns
nil
- Negative indices start from end
words=["this","that","these","those"]
puts words[2]
puts words[4]
puts words[-1]
these
nil
those
Changing Arrays
- Array contents can be changed
- Array sizes are reallocated dynamically
- Arrays can hold a mixture of objects
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
- Guess what? Arrays are object!
[] is the same as Array.new
- Array defines many useful methods
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
- aka dictionaries, maps, associative arrays
- object keys are used to access object values
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
- Hashes also have methods that accept blocks.
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?
{ |blah| ... } (or do |foo| ... end)?
- Code that you can pass as arguments to method calls.
- Think anonymous methods (that capture the context they're created in...)
- Useful for not repeating yourself in...
Blocks and Iteration
- Called method handles iterating through collection.
- The block simply uses each object in turn.
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
- Called method acquires and disposes of the resource.
- The block simply uses the resource.
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
- pass
each object in a collection to the provided block
open a file, pass it to the block, and then close the file
collect a new array using a block to transform elements of an old array
find_all objects that make the block return true
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/