# Mixins module Doubler def double self + self end end # simple 2D point class that includes the Doubler Mixin # Note: This class provides an implementation of + class AnotherPt attr_accessor :x, :y include Doubler def initialize(x=0, y=0) @x = x @y = y end def + other ans = AnotherPt.new ans.x = self.x + other.x ans.y = self.y + other.y ans end end AnotherPt.new(1, 2).double # Questionable style but still interesting... class Fixnum include Doubler end class String include Doubler end 2.double "hi".double # Comparable Example class House attr_accessor :price, :sqft include Comparable def initialize(price, sqft) @price = price @sqft = sqft end # Houses ordered by price, then sqft. # hint: @price/@sqft both implement <=> # hint2: <=> returns -1 for self < other, 0 self = other, +1 self > other def <=> other # TODO... end end h1 = House.new(10, 20) h2 = House.new(100, 20) h3 = House.new(10, 200) h1 < h2 # should be true h2 < h1 # should be false h1 == h1 # should be true h1 < h3 # should be true # Simple Enumerable Example class SimpleDeck attr_accessor :numbers, :face include Enumerable def initialize(numbers, face) @numbers = numbers @face = face end # First enumerate the numbers, then the face cards def each @numbers.each {|x| yield x} @face.each{|x| yield x} end end numbers = (1..9).to_a face = ["J", "Q", "K"] d = SimpleDeck.new(numbers, face) d.each {|x| puts x} d.map {|x| "MAPPED"} d.filter {|x| x.is_a? String } # Less Simple Enumberable Example class BinaryTree class Node attr_accessor :left, :right attr_reader :data def initialize(data, left=nil, right=nil) @data = data @left = left @right = right end end # Let's add 47 other awesome methods include Enumerable def insert el @root = insert_(el, @root) end def lookup el lookup_(el, @root) end def each # Note the "necessary block wrapping" each_(@root) { |x| yield x } end private def insert_ el, root return Node.new(el) unless root if el < root.data root.left = insert_(el, root.left) else root.right = insert_(el, root.right) end root end def lookup_ el, root return el if root.data == el if el < root.data lookup_(el, root.left) else lookup_(el, root.right) end end def each_ root if root each_(root.left) { |x| yield x } yield root.data each_(root.right) { |x| yield x } end end end b = BinaryTree.new b.insert 1 b.insert 0 b.insert 2 b.insert 3 b.each {|x| puts x} # prints nodes in pre-order traversal b.map {|x| x * 100} # pre-order traversal scaled by 100