I'm a newcomer to dynamic languages and have found quite an incredible
world among Ruby's .call, .method_missing and so on.  I've been
playing a bit to learn these features and I'd like comments from more
experienced folks on this bit of code.

#!/bin/ruby

class Triangle
  attr_accessor :base, :height, :area
  def initialize
    @base = 4.0
    @height = 5.0
    @area = 10.0
    @formulas = {
      "area"   => Proc.new { @base * @height / 2.0 },
      "base"   => Proc.new { @area * 2 / @height.to_f }, 
      "height" => Proc.new { @area * 2 / @base.to_f }
    }
    @solve_prefix = "solve_for_"
  end

  def method_missing(method_id, *args)
    method_name = method_id.to_s

    if method_name =~ /^#{@solve_prefix}/
      variable_name = method_name.gsub(@solve_prefix, "")
      solve_for(variable_name)
    else
      super
    end
  end

  def to_s
    "Base: #{@base}\nHeight: #{@height}\nArea: #{@area}\n"
  end

  private

  def solve_for(variable_name)
    writer = method( variable_name + "=" ) # look for `xxx=' method
    formula = @formulas[variable_name]     # get the right formula
    value = formula.call                   # execute it
    writer.call( value )                   # write its value
  end

end


if $0 == __FILE__
  t = Triangle.new
  puts t
  puts "Now changing base and solving for area..."
  t.base = 5
  t.solve_for_area
  puts t
  puts "Now changing area and solving for height..."
  t.area = 50
  t.solve_for_height
  puts t
end



The one thing I would have liked to do but have not been able to, was
of using :symbol's instead of strings as keys for the @formulas hash.
The difficulty arose in method_missing when trying to get the :symbol
from the variable (didn't find anything that looks like
"a".to_symbol).  I don't know whether it would have made any
difference in performance, though.  I don't even know if in terms of
performance it is any good, for that matter.  But, as I said, I was
mostly playing. :-)

Massimiliano