I recently picked up the book Seven Languages in Seven Weeks. This books runs through seven programming languages and shows you how to use them. It skips much of the basics under the assumption that you already have programming experience and so understand data types, can look up api documentation, etc. by yourself. Instead it intends to only focus on what is interesting about each language and only gives instruction on how to use those features and api's that make the language stand out.

I primarily picked the book up for everything it covers other than Ruby, but Ruby is the first chapter, so that's what I'm on. Some of the exercises the book has you do may get somewhat challenging and some googling suggests people do have trouble with some of them. With that in mind, I am going to document my solutions to exercises that I found interesting or that looked like they could be troublesome to someone.

First off is exercise two of day two. In this exercise you are given a program with a class who's constructor takes a string and array of children and builds a tree of the objects. The goal is to modify it so that you can just pass a hash of hashes (of hashes of hashes of hashes ad nauseum) into the constructor and it will build the tree out.

Here is my solution:

class Tree
  attr_accessor :children, :node_name

  def initialize(tree = {})
    name,nodes = tree.shift
    @node_name = name
    @children = []

    nodes.each {|key,value|
      @children.push(Tree.new(key => value))
    }

  end

  def visit_all(&block)
    visit &block
    children.each {|c| c.visit_all &block}
  end

  def visit(&block)
    block.call self
  end
end

ruby_tree = Tree.new("Ruby" => {"some tree" => {}, "Reia" => {}, "MacRuby" => {"Another Tree" => {}}})

puts "Visiting a node"
ruby_tree.visit {|node| puts node.node_name}
puts

puts "visiting entire tree"
ruby_tree.visit_all {|node| puts node.node_name}

require 'pp'
pp ruby_tree

In the initialize() method I shift the hash that is passed in which gives me the first node name and the rest of the hash. The node names of that hash are the children of the first node, so I call each on that hash, which creates a new hash for each child, and then I create a new tree with that hash and push it onto the children array of the current tree.

The output looks good to me:

justin@DebianLenny:~/ruby$ ruby day2-2.rb
Visiting a node
Ruby

visiting entire tree
Ruby
Reia
some tree
MacRuby
Another Tree
#<Tree:0xb7ce7a7c
 @children=
  [#<Tree:0xb7ce79c8 @children=[], @node_name="Reia">,
   #<Tree:0xb7ce7964 @children=[], @node_name="some tree">,
   #<Tree:0xb7ce7900
     @children=[#<Tree:0xb7ce784c @children=[], @node_name="Another Tree">],
    @node_name="MacRuby">],
  @node_name="Ruby">