Wednesday, December 10, 2014

7L7W Week 1: Ruby Day 2>Take 2

Reading through the 3rd day's treatment and I decided to go back over this exercise from day 2.
This is better. I'm still not entirely convinced.
class Hash
  def each_hash
    h = self
    h.each do |element|
      yield({element[0] => element[1]})
    end
  end
end
class Tree
  attr_accessor :children, :node_name

  def initialize(name, children=[])
    if name.is_a?(String)
      @node_name = name
    elsif name.is_a?(Hash)
      @node_name = name.keys[0]
      name[@node_name].each_hash {|trunk|
        children << Tree.new(trunk)
        }
    end
    @children = children
  end
  
  def visit_all(&block)
    visit &block
    children.each {|c| c.visit_all &block}
  end
  
  def visit(&block)
    block.call self
  end
end

familyTree = Tree.new({'grandpa' => {'dad' => {'child 1' => {}, 'child 2' => {}}, 'uncle' => {'child 3' => {}, 'child 4' => {}}}})
puts "Visiting a node"
familyTree.visit {|node| puts node.node_name}
puts

puts "Visiting entire tree"
familyTree.visit_all {|node| puts node.node_name}


The notion of editing the base class at will and indeed the basic predefined classes/types, while apparently being an integral part of Ruby's design, doesn't come easily. And still this solution requires testing the type of the incoming parameter, making Ruby's blasé treatment of types rather dubious. Or, I'm doing it wrong™ which is also quite possible seeing as this is exactly the 3rd day I've done anything in Ruby.

What I've done here is basically the same as a C# extension method. What gives me the 'icks' is the notion of directly altering Hash.each to do what I wanted it to do. It seems that you can't scope the changes so it's a global edit of the existing class. Great power, &etc, plus TDD, but if anyone comes along later to update the script and tries to do anything with a hash while those changes are in effect it's going to bite them in the tail.

I think I'm feeling a tension between reducing failures and productivity at the cost of stability. It's hard to decide where the sweet spot is there. That's interesting since I spent a good bit of time developing in PHP which is pretty loosely typed.

No comments: