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
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
‘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
of the values yielded by #each 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 Monday, August 1, 2011
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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 end end Monday, August 1, 2011