Presented at Cascadia Ruby Conf 2011 July 29, 2011 in Seattle, WA by Haris Amin. The presentation can be viewed here http://confreaks.net/videos/607-cascadiaruby2011-the-enumerable-module-or-how-i-fell-in-love-with-ruby
08448380779 Call Girls In Diplomatic Enclave Women Seeking Men
The Enumerable Module or How I Fell in Love with Ruby
1. THE ENUMERABLE MODULE
or How I Fell In Love with Ruby!
Haris Amin
Cascadia Ruby Conf 2011
07/29/2011
Monday, August 1, 2011
2. WHO IS THIS GUY?
• Haris Amin
• Software/Web Developer
• Live in New York City
Monday, August 1, 2011
3. THESE GUYS MAKE SURE I’M
NOT LIVING IN THE STREETS
Monday, August 1, 2011
4. WHAT WE DO @
?
Shoulder Pressing Colleagues
Healthy Programmer
Vertebrates
Monday, August 1, 2011
5. LOOK MA I HAS DEGREE!
• Studies Physics/Math in Undergrad
•E = mc^2 , doesn’t pay for food
• Programming, for me in college was just a means to compute
something
Monday, August 1, 2011
6. LAST TALK I GAVE AT A
CONFERENCE?
• Simulation of Viscoelastic Fluids
• What did I do?
• Employed a weighted-norm least-squares finite element
method to approximate the solution to Oldroyd-B equations
• So...yeah... for me programming was just a way to compute
stuff :)
Monday, August 1, 2011
8. WHAT IS THE ENUMERABLE
MODULE?
•A module, you can MIX IT IN!
•A bunch of methods that work with collections
• Empowers the most notably the Array and Hash classes
(among others i.e. Set, Range, File, etc.)
Monday, August 1, 2011
9. HOW TO ‘MIX-IN’ THE
ENUMERABLE?
•A class ‘including’ or ‘mixing-in’ Enumerable must define the
‘#each’ method
• Yielded items from the #each method empower the
collection awareness for the class
Monday, August 1, 2011
10. class PlanetExpress
include Enumerable
def each
yield “Bender”
yield “Frye”
yield “Leela”
yield “Zoidberg”
end
end
PlanetExpress.new.collect do |member|
“#{member} works at Planet Express”
end
• The #collect method executes the provided block
to all of the values yielded by #each
Monday, August 1, 2011
11. BUT WHY IS ENUMERABLE
SO...
...
...
...
SEXY!?
Monday, August 1, 2011
12. LOOK AT ALL THESE
METHODS!
• all?, any?, collect, detect, each_cons, each_slice,
each_with_index, entries, enum_cons,
enum_slice, enum_with_index, find, find_all,
grep, include?, inject, map, max, member?, min,
partition, reject, select, sort, sort_by, to_a,
to_set, zip
Monday, August 1, 2011
13. PROGRAMMER
HAPPINESS
“Programmers often feel joy when they can concentrate on
the creative side of programming, so Ruby is designed to
make programmers happy.”
- Yukihiro Matsumoto (Matz)
Monday, August 1, 2011
14. WATCH OUT FOR DR.
ZOIDBERG’S TIPS
Monday, August 1, 2011
15. LET’S TAKE A LOOK AT SOME
ENUMERABLE METHODS...
Monday, August 1, 2011
16. each
names = %w{ Frye Leela Zoidberg }
names.each do |name|
“#{name} works at Planet Express”
end
• The #each method yields items to a supplied block of
code one at a time
• Classes implement #each differently
Monday, August 1, 2011
17. find
names = %w{ Frye Leela Zoidberg }
names.find { |name| name.length > 4}
• Elegantly simple, find one item that matches the
condition supplied by the block
• Consider how a library like ActiveRecord would
reimplemnt find from Enumerable?
Monday, August 1, 2011
18. group_by
names = %w{ Frye Bender Leela Zoidberg }
names.group_by { |name| name.length}
# => {4=>["Frye"], 6=>["Bender"], 5=>["Leela"], 8=>["Zoidberg"]}
• It takes a block, and returns a hash, with the returned
value from the block set as the key
• Consider how one could use this as word count for a
document/text
Monday, August 1, 2011
19. grep
names = %w{ Frye Bender Leela Zoidberg }
names.grep(/oidber/)
# => ["Zoidberg"]
• Searches for members of the collection according to a
pattern.... pattern matching
• It uses the === operator for pattern matching
Monday, August 1, 2011
20. GREP-ALICOUS!
stuff = [ “Zoidberg”, Pizza.new, :homeless, “Dr."]
stuff.grep(String)
# => [ “Zoidberg”, “Dr.”]
• Using the === allows us to do some fancy matching
• We can grep for types or objects
• Equivalent to stuff.select { |element| String === element}
Dr. Zoidberg’s Tip (The doctor is in!)
Monday, August 1, 2011
21. map / collection
names = %w{ Frye Bender Leela Zoidberg }
names.map { |name| name.downcase }
# => [“frye”, “bender”, “leela”, “zoidberg” ]
• Think of it as a transformation method, that applies the
block as a transformation
• Always returns a new Array with the transformation
applied
• Different then #each, return value matters with #map
Monday, August 1, 2011
23. ENUMERATOR
• We can create an Enumerator without mixing-in the
Enumerable module and still have the power of Enumerable
methods
•3 ways to create Enumerator without mixing-in Enumerable
1. Create Enumerator explicitly with a code block
2. Attach an Enumerator to another object
3. Create Enumerator implicitly with blockless iterators
Monday, August 1, 2011
24. Create Enumerator explicitly with a code block
e = Enumerator.new do |y|
y << “Frye”
y << “Bender”
y << “Leela”
y << “Zoidberg”
end
•y is the yielder, an instance of Enumerator::Yielder
• You don’t yield from the block, you only append to the
yielder
Monday, August 1, 2011
25. Attach an Enumerator to another object
names = %w { Frye Bender Leela Zoidberg }
e = names.enum_for(:select)
• knows/learns how to implement #each from another object
• we’re binding the Enumerator to the #select method of the
names array
Monday, August 1, 2011
26. Create Enumerator implicitly with blockless iterators
names = %w { Frye Leela Bender }
names.enum_for(:select)
# => #<Enumerator: ["Frye", "Leela", "Bender"]:map>
names.map
# => #<Enumerator: ["Frye", "Leela", "Bender"]:map>
• most iterators when called without a block return an
Enumerator
• our blockless iterator returned the same Enumerator as the
enum_for approach
Monday, August 1, 2011
27. BUT WHY DO WE CARE?
...USES?
Monday, August 1, 2011
28. Add Enumerability to an existing object
module PlanetExpress
class Ship
PARTS= %w{ sprockets black-matter }
def survey_parts
PARTS.each {|part| yield part }
end
end
end
ship = PlanetExpress::Ship.new
enum = ship.enum_for(:survey_parts)
• Now we can use Enumerable methods on our ship object
Monday, August 1, 2011
29. Fine Grained Iteration
scenes = %w{ credits opening climax end }
e = scenes
puts e.next
puts e.next
e.rewind puts e.next
• An Enumerator is an object, it can maintain state
• Think film reels, state machines, etc...
Monday, August 1, 2011
31. CHAINING ENUMERATORS
• Normally chaining enumerators isn’t very useful
• names.map.select might as well be names.select
• Most enumerators are just passing the array of values down
the chain
Monday, August 1, 2011
32. LAZY SLICE
names = %w { Frye Bender Leela Zoidberg }
names.each_slice(2).map do |first, second|
“#{first} gets a slice & #{second} gets a slice”
end
• Instead of creating a 2-element slices for the whole
array in memory, the enumerator can create slices in a
“lazy” manner and only create them as they are
needed
Dr. Zoidberg’s Tip (can i have a slice)
Monday, August 1, 2011
33. MAP WITH INDEX...WTF?
names = %w { Leela Bender Frye Zoidberg }
names.map.with_index do |name, i|
“#{name} has a rank #{i}”
end
• There is no #map_with_index defined in Enumerable
• Ah but we can chain... chain... chain!
Dr. Zoidberg’s Tip (what map? i don’t even know where we are!)
Monday, August 1, 2011
35. WHAT IS SET?
• The Set class is a Standard Lib class in Ruby
• You use it by requiring it explicitly ( require ‘set’ )
• It stores a collection of unordered, unique values
• It mixes-in the Enumerable module
Monday, August 1, 2011
36. SET IS ENUMERABLE
class Set
include Enumerable
#...
def each
block_given? or return enum_for(__method__)
@hash.each_key { |o| yield(o) }
self
end
end
• Calls a block for each member of the set passing the member
as a parameter
• Returns an enumerator if no block is given
Monday, August 1, 2011
37. SET IS ENUMERABLE
class Set
include Enumerable
#...
def initialize
@hash ||= Hash.new
enum.nil? and return
if block
do_with_enum(enum) { |o| add(block[o]) }
else
merge(enum)
end
end
end
• Actually uses Hash for implementing unique values
Monday, August 1, 2011
38. SET IS ENUMERABLE
class Set
include Enumerable
#...
def include?
@hash.include?(o)
end
alias member? include?
end
• Defines its own implementation of Enumerable methods
Monday, August 1, 2011
40. THEN READ THIS
• Thistalk was inspired by the AWESOME discussion of
Enumerable by David A. Black
• READ IT! SPREAD THE WORD!!!!
Monday, August 1, 2011
41. THANK YOU!
hamin
harisamin
harisamin.tumblr.com
Monday, August 1, 2011