The Enumerable Module or How I Fell in Love with Ruby
-
Upload
harisamin -
Category
Technology
-
view
9.453 -
download
1
description
Transcript of The Enumerable Module or How I Fell in Love with Ruby
THE ENUMERABLE MODULEor How I Fell In Love with Ruby!
Haris Amin
Cascadia Ruby Conf 2011
07/29/2011
Monday, August 1, 2011
WHO IS THIS GUY?
• Haris Amin
• Software/Web Developer
• Live in New York City
Monday, August 1, 2011
THESE GUYS MAKE SURE I’M NOT LIVING IN THE STREETS
Monday, August 1, 2011
WHAT WE DO @?
Shoulder Pressing Colleagues
Healthy Programmer Vertebrates
Monday, August 1, 2011
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
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
THOUGHT TO MYSELF...
Arrays & Hashes
ARE FUN!!!!
Monday, August 1, 2011
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
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
• The #collect method executes the provided block to all of the values yielded by #each
class PlanetExpress include Enumerable
def each yield “Bender” yield “Frye” yield “Leela” yield “Zoidberg” endend
PlanetExpress.new.collect do |member| “#{member} works at Planet Express”end
Monday, August 1, 2011
BUT WHY IS ENUMERABLE SO...
SEXY!?
...
...
...
Monday, August 1, 2011
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
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
WATCH OUT FOR DR. ZOIDBERG’S TIPS
Monday, August 1, 2011
LET’S TAKE A LOOK AT SOME ENUMERABLE METHODS...
Monday, August 1, 2011
each
• The #each method yields items to a supplied block of code one at a time
• Classes implement #each differently
names = %w{ Frye Leela Zoidberg }
names.each do |name| “#{name} works at Planet Express”end
Monday, August 1, 2011
find
• Elegantly simple, find one item that matches the condition supplied by the block
• Consider how a library like ActiveRecord would reimplemnt find from Enumerable?
names = %w{ Frye Leela Zoidberg }
names.find { |name| name.length > 4}
Monday, August 1, 2011
group_by
• 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
names = %w{ Frye Bender Leela Zoidberg }
names.group_by { |name| name.length}# => {4=>["Frye"], 6=>["Bender"], 5=>["Leela"], 8=>["Zoidberg"]}
Monday, August 1, 2011
grep
• Searches for members of the collection according to a pattern.... pattern matching
• It uses the === operator for pattern matching
names = %w{ Frye Bender Leela Zoidberg }
names.grep(/oidber/)# => ["Zoidberg"]
Monday, August 1, 2011
GREP-ALICOUS!
• 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!)
stuff = [ “Zoidberg”, Pizza.new, :homeless, “Dr."]stuff.grep(String)# => [ “Zoidberg”, “Dr.”]
Monday, August 1, 2011
map / collection
• 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
names = %w{ Frye Bender Leela Zoidberg }
names.map { |name| name.downcase }# => [“frye”, “bender”, “leela”, “zoidberg” ]
Monday, August 1, 2011
THE DELICIOUS ENUMERATOR... enum ... enum ... enum
Monday, August 1, 2011
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
Create Enumerator explicitly with a code block
• y is the yielder, an instance of Enumerator::Yielder
• You don’t yield from the block, you only append to the yielder
e = Enumerator.new do |y| y << “Frye” y << “Bender” y << “Leela” y << “Zoidberg”end
Monday, August 1, 2011
Attach an Enumerator to another object
• knows/learns how to implement #each from another object
• we’re binding the Enumerator to the #select method of the names array
names = %w { Frye Bender Leela Zoidberg }e = names.enum_for(:select)
Monday, August 1, 2011
Create Enumerator implicitly with blockless iterators
•most iterators when called without a block return an Enumerator
• our blockless iterator returned the same Enumerator as the enum_for approach
names = %w { Frye Leela Bender }
names.enum_for(:select)# => #<Enumerator: ["Frye", "Leela", "Bender"]:map>
names.map# => #<Enumerator: ["Frye", "Leela", "Bender"]:map>
Monday, August 1, 2011
BUT WHY DO WE CARE?
...USES?
Monday, August 1, 2011
Add Enumerability to an existing object
•Now we can use Enumerable methods on our ship 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)
Monday, August 1, 2011
Fine Grained Iteration
• An Enumerator is an object, it can maintain state
• Think film reels, state machines, etc...
scenes = %w{ credits opening climax end } e = scenes puts e.nextputs e.nexte.rewind puts e.next
Monday, August 1, 2011
CHAINING ENUMERATORS...
...HMMM
Monday, August 1, 2011
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
LAZY SLICE
• 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)
names = %w { Frye Bender Leela Zoidberg }names.each_slice(2).map do |first, second| “#{first} gets a slice & #{second} gets a slice”end
Monday, August 1, 2011
MAP WITH INDEX...WTF?
• 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!)
names = %w { Leela Bender Frye Zoidberg }names.map.with_index do |name, i| “#{name} has a rank #{i}”end
Monday, August 1, 2011
THE SET CLASS
Monday, August 1, 2011
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
SET IS ENUMERABLEclass Set include Enumerable #... def each block_given? or return enum_for(__method__) @hash.each_key { |o| yield(o) } self endend
• 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
SET IS ENUMERABLE
• Actually uses Hash for implementing unique values
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 endend
Monday, August 1, 2011
SET IS ENUMERABLE
•Defines its own implementation of Enumerable methods
class Set include Enumerable #... def include? @hash.include?(o) end alias member? include?end
Monday, August 1, 2011
ARE YOU IN LOVE YET?
Monday, August 1, 2011
THEN READ THIS
• This talk was inspired by the AWESOME discussion of Enumerable by David A. Black• READ IT! SPREAD THE WORD!!!!
Monday, August 1, 2011
THANK YOU!
hamin
harisamin
harisamin.tumblr.com
Monday, August 1, 2011