Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Ruby Enumerable

Ruby Enumerable

Very basic talk on Ruby enumerable module.

Damien Roche

October 13, 2014
Tweet

Other Decks in Programming

Transcript

  1. In The Wild Example of classes that inherit from Enumerable:

    Array # [1,2,3] Hash # { a: “hash” } Range # (3..1) File # File.new('myfile.txt') Dir # Dir.pwd Struct # Struct.new(:attrib1, :attrib2)
  2. any?, all?, include?, none? ["is", "there"].any? { |word| word >

    4 } # => true [1,2,3].all? { |i| i.is_a? Integer } # => true ["does", "this"].include? { |a| a == "stutter" } # => false ["I", "have"].none? { |word| word == "none" } # => true
  3. map, select, reject, inject select returns a new array [1,

    "two", 3, "four"].select { |element| element.is_a? String } # => ["two", "four"] reject does opposite of select [1, "two", 3, "four"].reject { |element| element.is_a? String } # => [1, 3] map applies block to each element and returns new array ["DONT", "SHOUT"].map { |word| word.downcase } # => ["dont", "shout"] inject...well, does this ["pay", "attention"].inject(0) do |counter, word| counter += word.length end
  4. cycle, zip, partition cycle applies block to each element n

    times (note: forever as default!) ["a", "b", "c"].cycle { |word| puts word } # => "a", "b", "c", "a", "b" ... forever ["a", "b", "c"].cycle(2) { |word| puts word } # => "a", "b", "c", "a", "b", "c" zip merges elements of multiple arrays [1,3,5].zip([2,4,6]) # => [[1, 2], [3, 4], [5, 6]] partition returns two arrays. First where passed block is true. Second for rest. (1..6).partition? { |i| i.even? } # => [[2, 4, 6], [1, 3, 5]]
  5. These are aliased methods (uncommon → common): collect → map

    detect → find find_all → select reduce → inject
  6. Mixin Example class DogEnumerator include Enumerable def initialize(dogs) @dogs =

    dogs end def each(&block) @dogs.each do |dog| if block_given? block.call(dog) else yield dog end end end end dogs = DogEnumerator.new(["Scooby", "Pluto"]) dogs.include? "Scooby" # => true • each(...) method to the left must be defined for class to behave correctly. • When you include Enumerable module you get a bunch of helpful methods that allow your class to behave like an enumerator. • Array inherits from Enumerable and makes heavy use of this functionality so all your favourite methods are available (any?, all?, include?, select) • Note: there are differences. Bang/dangerous methods are not available in Enumerable. Why?
  7. Enumerable and comparisons When using Enumerable max/min/sort functionality, we need

    to additionally implement a three-way comparison method '<=>'. class FilmEnumerator include Enumerable def initialize @films = [ "1984", "2001: Space Odyssey", "1492: Conquest of Paradise" ] end def each... (references @films) def <=>(this, other) # turn back this.match(/\d{4}/)[0].to_i <=> other.match(/\d{4}/)[0].to_i end end fe = FilmEnumerator.new fe.sort # => ["1492: Conquest of Paradise", "1984", "2001: Space Odyssey"] '<=>' is called a spaceship operator/method, which has the following returns: a <=> b if a < b then return -1 if a == b then return 0 if a > b then return 1
  8. Suggested Reading • http://ruby-doc.org/core-2.1.3/Enumerable.html • Punish yourself: • Enumerable vs

    Enumerator • Tutorials: • http://ruby.bastardsbook.com/chapters/enumerables/ • https://practicingruby.com/articles/building-enumerable- and-enumerator