<?xml version="1.0" encoding="UTF-8"?>
<feed xml:lang="en-US" xmlns="http://www.w3.org/2005/Atom">
  <title>&#198;therical - syndicated</title>
  <id>tag:aetherical.com,2008:mephisto/syndicated</id>
  <generator uri="http://mephistoblog.com" version="0.7.3">Mephisto Noh-Varr</generator>
  <link href="http://aetherical.com/feed/syndicated/atom.xml" rel="self" type="application/atom+xml"/>
  <link href="http://aetherical.com/syndicated" rel="alternate" type="text/html"/>
  <updated>2008-06-25T14:55:51Z</updated>
  <entry xml:base="http://aetherical.com/">
    <author>
      <name>Matt Williams</name>
    </author>
    <id>tag:aetherical.com,2008-06-25:84</id>
    <published>2008-06-25T14:27:00Z</published>
    <updated>2008-06-25T14:55:51Z</updated>
    <category term="blog"/>
    <category term="syndicated"/>
    <category term="metaprogramming"/>
    <category term="programming"/>
    <category term="ruby"/>
    <link href="http://aetherical.com/2008/6/25/a-class-is-not-always-a-class" rel="alternate" type="text/html"/>
    <title>A Class is not always a Class</title>
<content type="html">
            &lt;p&gt;While playing around in irb last night, I discovered something interesting  Class does not always have the same superclass:&lt;/p&gt;
&lt;pre&gt;
&lt;table class=&quot;CodeRay&quot;&gt;&lt;tr&gt;
  &lt;td title=&quot;click to toggle&quot; class=&quot;line_numbers&quot;&gt;&lt;pre&gt;1&lt;tt&gt;
&lt;/tt&gt;2&lt;tt&gt;
&lt;/tt&gt;3&lt;tt&gt;
&lt;/tt&gt;4&lt;tt&gt;
&lt;/tt&gt;&lt;strong&gt;5&lt;/strong&gt;&lt;tt&gt;
&lt;/tt&gt;6&lt;tt&gt;
&lt;/tt&gt;7&lt;tt&gt;
&lt;/tt&gt;8&lt;tt&gt;
&lt;/tt&gt;9&lt;tt&gt;
&lt;/tt&gt;&lt;strong&gt;10&lt;/strong&gt;&lt;tt&gt;
&lt;/tt&gt;11&lt;tt&gt;
&lt;/tt&gt;12&lt;tt&gt;
&lt;/tt&gt;13&lt;tt&gt;
&lt;/tt&gt;14&lt;tt&gt;
&lt;/tt&gt;&lt;strong&gt;15&lt;/strong&gt;&lt;tt&gt;
&lt;/tt&gt;16&lt;tt&gt;
&lt;/tt&gt;17&lt;tt&gt;
&lt;/tt&gt;18&lt;tt&gt;
&lt;/tt&gt;19&lt;tt&gt;
&lt;/tt&gt;&lt;strong&gt;20&lt;/strong&gt;&lt;tt&gt;
&lt;/tt&gt;21&lt;tt&gt;
&lt;/tt&gt;22&lt;tt&gt;
&lt;/tt&gt;23&lt;tt&gt;
&lt;/tt&gt;24&lt;tt&gt;
&lt;/tt&gt;&lt;strong&gt;25&lt;/strong&gt;&lt;tt&gt;
&lt;/tt&gt;26&lt;tt&gt;
&lt;/tt&gt;27&lt;tt&gt;
&lt;/tt&gt;28&lt;tt&gt;
&lt;/tt&gt;29&lt;tt&gt;
&lt;/tt&gt;&lt;strong&gt;30&lt;/strong&gt;&lt;tt&gt;
&lt;/tt&gt;31&lt;tt&gt;
&lt;/tt&gt;32&lt;tt&gt;
&lt;/tt&gt;33&lt;tt&gt;
&lt;/tt&gt;34&lt;tt&gt;
&lt;/tt&gt;&lt;strong&gt;35&lt;/strong&gt;&lt;tt&gt;
&lt;/tt&gt;36&lt;tt&gt;
&lt;/tt&gt;37&lt;tt&gt;
&lt;/tt&gt;38&lt;tt&gt;
&lt;/tt&gt;&lt;/pre&gt;&lt;/td&gt;
  &lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;tt&gt;
&lt;/tt&gt;&amp;gt;&amp;gt; &lt;span class=&quot;co&quot;&gt;Class&lt;/span&gt;.superclass&lt;tt&gt;
&lt;/tt&gt;=&amp;gt; &lt;span class=&quot;co&quot;&gt;Module&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;&amp;gt;&amp;gt; &lt;span class=&quot;co&quot;&gt;Class&lt;/span&gt;.object_id&lt;tt&gt;
&lt;/tt&gt;=&amp;gt; &lt;span class=&quot;i&quot;&gt;-605542778&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;&amp;gt;&amp;gt; &lt;span class=&quot;r&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;cl&quot;&gt;Fud&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;&amp;gt;&amp;gt;   &lt;span class=&quot;r&quot;&gt;end&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;=&amp;gt; &lt;span class=&quot;pc&quot;&gt;nil&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;&amp;gt;&amp;gt; &lt;span class=&quot;co&quot;&gt;Fud&lt;/span&gt;.class&lt;tt&gt;
&lt;/tt&gt;=&amp;gt; &lt;span class=&quot;co&quot;&gt;Class&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;&amp;gt;&amp;gt; &lt;span class=&quot;co&quot;&gt;Fud&lt;/span&gt;.object_id&lt;tt&gt;
&lt;/tt&gt;=&amp;gt; &lt;span class=&quot;i&quot;&gt;-606747838&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;&amp;gt;&amp;gt; &lt;span class=&quot;co&quot;&gt;Fud&lt;/span&gt;.superclass&lt;tt&gt;
&lt;/tt&gt;=&amp;gt; &lt;span class=&quot;co&quot;&gt;Object&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;&amp;gt;&amp;gt; &lt;span class=&quot;co&quot;&gt;Class&lt;/span&gt;.class&lt;tt&gt;
&lt;/tt&gt;=&amp;gt; &lt;span class=&quot;co&quot;&gt;Class&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;&amp;gt;&amp;gt; &lt;span class=&quot;co&quot;&gt;Class&lt;/span&gt;.class.superclass&lt;tt&gt;
&lt;/tt&gt;=&amp;gt; &lt;span class=&quot;co&quot;&gt;Module&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;&amp;gt;&amp;gt; &lt;span class=&quot;co&quot;&gt;Fud&lt;/span&gt;.class.superclass&lt;tt&gt;
&lt;/tt&gt;=&amp;gt; &lt;span class=&quot;co&quot;&gt;Module&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;&amp;gt;&amp;gt; &lt;span class=&quot;co&quot;&gt;Fud&lt;/span&gt;.class.object_id&lt;tt&gt;
&lt;/tt&gt;=&amp;gt; &lt;span class=&quot;i&quot;&gt;-605542778&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;&amp;gt;&amp;gt; &lt;span class=&quot;co&quot;&gt;Fud&lt;/span&gt;.class&lt;tt&gt;
&lt;/tt&gt;=&amp;gt; &lt;span class=&quot;co&quot;&gt;Class&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;&amp;gt;&amp;gt; &lt;span class=&quot;co&quot;&gt;Fud&lt;/span&gt;.class&lt;tt&gt;
&lt;/tt&gt;=&amp;gt; &lt;span class=&quot;co&quot;&gt;Class&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;&amp;gt;&amp;gt; &lt;span class=&quot;co&quot;&gt;Fud&lt;/span&gt;.class.object_id&lt;tt&gt;
&lt;/tt&gt;=&amp;gt; &lt;span class=&quot;i&quot;&gt;-605542778&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;&amp;gt;&amp;gt; &lt;span class=&quot;co&quot;&gt;Fud&lt;/span&gt;.superclass&lt;tt&gt;
&lt;/tt&gt;=&amp;gt; &lt;span class=&quot;co&quot;&gt;Object&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;&amp;gt;&amp;gt; &lt;span class=&quot;co&quot;&gt;Fud&lt;/span&gt;.instance_of? &lt;span class=&quot;co&quot;&gt;Class&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;=&amp;gt; &lt;span class=&quot;pc&quot;&gt;true&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;&amp;gt;&amp;gt; &lt;span class=&quot;co&quot;&gt;Class&lt;/span&gt;.instance_of? &lt;span class=&quot;co&quot;&gt;Class&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;=&amp;gt; &lt;span class=&quot;pc&quot;&gt;true&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;&amp;gt;&amp;gt; &lt;span class=&quot;co&quot;&gt;Class&lt;/span&gt;.class.object_id&lt;tt&gt;
&lt;/tt&gt;=&amp;gt; &lt;span class=&quot;i&quot;&gt;-605542778&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;&amp;gt;&amp;gt; &lt;span class=&quot;co&quot;&gt;Class&lt;/span&gt;.object_id&lt;tt&gt;
&lt;/tt&gt;=&amp;gt; &lt;span class=&quot;i&quot;&gt;-605542778&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;/tr&gt;&lt;/table&gt;

&lt;/pre&gt;
&lt;p&gt;Curious, huh?  So, despite Fud being an instance of Class, it's superclass is Object.  And Class is an instance of itself.&lt;/p&gt;
&lt;p&gt;I believe that this has to do with the mysterious &quot;class&quot; object which every class has.  This class object allows one to get at the guts, if you will, of a class in order to do metaprogramming.&lt;/p&gt;
&lt;p&gt;Still it's pretty interesting...&lt;/p&gt;
          </content>  </entry>
  <entry xml:base="http://aetherical.com/">
    <author>
      <name>Matt Williams</name>
    </author>
    <id>tag:aetherical.com,2008-05-27:73</id>
    <published>2008-05-27T22:26:00Z</published>
    <updated>2008-05-27T22:37:27Z</updated>
    <category term="blog"/>
    <category term="syndicated"/>
    <category term="programming"/>
    <category term="ruby"/>
    <link href="http://aetherical.com/2008/5/27/reducing-code-smell" rel="alternate" type="text/html"/>
    <title>Reducing Code Smell</title>
<content type="html">
            &lt;p&gt;I had an instance where I'd written some code, using hashes, and knew that there had to be a better way to do it.  Performing an &lt;code&gt;inject&lt;/code&gt; and adding elements to a hash doesn't work:
    h[a] = 1
returns the value, not the hash.  Here's the smelly code (variables, etc., changed to protect the guilty):&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;# possibilities is an array
def intersectors(possibilities = [], interceptors = [])
  return { } if possibilities.nil?
  interceptors.inject({ }) do |h, interceptor|
    # returns an array 
    z = foo(interceptor)
    intersect = possibilities &amp;amp; z
    h[interceptor] = intersect unless intersect.empty?
    h
  end
end
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;So, then I decided to RTFM and found &lt;code&gt;merge&lt;/code&gt;.  It makes it a lot tighter:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;def intersectors(path = [], interceptors = [])
  return { } if path.nil?
  interceptors.inject({ }) do |h, interceptor|
    h.merge(interceptor =&amp;gt; x) unless (x=(path &amp;amp; foo(interceptor))).empty?
  end
end
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Better, too, I think; I don't have that extraneous &lt;code&gt;h&lt;/code&gt; laying around.....  I'm also using some syntactic sugar -- ruby is smart enough to make a hash of key/value pairs in a method call, so long as they're the last entities to be passed.&lt;/p&gt;

&lt;p&gt;I'm not saying it's baby-fresh, but it certainly stinks less.....&lt;/p&gt;
          </content>  </entry>
  <entry xml:base="http://aetherical.com/">
    <author>
      <name>Matt Williams</name>
    </author>
    <id>tag:aetherical.com,2008-05-27:72</id>
    <published>2008-05-27T21:21:00Z</published>
    <updated>2008-05-27T21:27:29Z</updated>
    <category term="blog"/>
    <category term="syndicated"/>
    <category term="metaprogramming"/>
    <category term="programming"/>
    <category term="ruby"/>
    <link href="http://aetherical.com/2008/5/27/attributes-revisited-booleans" rel="alternate" type="text/html"/>
    <title>Attributes Revisited: Booleans</title>
<content type="html">
            &lt;p&gt;While writing some code last night, I realized that I'd left out something from my attributes -- the ability to do booleans such as &lt;code&gt;obj.nil?&lt;/code&gt; and have the boolean method created for me.   So, the new, improved attributes code -- now with boolean action follows:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;class Object
  def self.attribute(*arg,&amp;amp;block)
    (name, default) = arg
    short_name = name.to_s.sub(/\?/,&quot;&quot;)
    self.send(:define_method, name) {
      if instance_variables.include? &quot;@#{short_name}&quot;
           self.instance_eval &quot;@#{short_name}&quot;
      else
        if block_given?
          instance_eval &amp;amp;block
        else
          default
        end
      end
    }
    self.send(:define_method, &quot;#{short_name}=&quot;){ |value|
      self.instance_eval &quot;@#{short_name} = value&quot;
    }
  end
end
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;I wonder what other behaviours I can add......  just kidding.&lt;/p&gt;
          </content>  </entry>
  <entry xml:base="http://aetherical.com/">
    <author>
      <name>Matt Williams</name>
    </author>
    <id>tag:aetherical.com,2008-05-27:71</id>
    <published>2008-05-27T20:47:00Z</published>
    <updated>2008-05-28T16:57:36Z</updated>
    <category term="blog"/>
    <category term="syndicated"/>
    <category term="pecha-kucha"/>
    <category term="presentations"/>
    <category term="web2.0"/>
    <link href="http://aetherical.com/2008/5/27/web-2-0-pecha-kucha-style" rel="alternate" type="text/html"/>
    <title>Web 2.0: Pecha Kucha Style</title>
<content type="html">
            &lt;p&gt;&lt;a href=&quot;http://www.pecha-kucha.org&quot;&gt;Pecha Kucha&lt;/a&gt; is a presentation style consisting of 20 slides, with 20 seconds/slide.  I got tapped last Tuesday for giving a presentation on Thursday.  It was a bit of a rush job, and I was a bit harried, but all in all, a good experience.&lt;/p&gt;

&lt;h3&gt;Thoughts&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;It's not an &lt;em&gt;easy&lt;/em&gt; style.  The slides go one to the other every 20 seconds, whether you're ready or not.&lt;/li&gt;
&lt;li&gt;I've found that I need to be much better prepared -- given only 20 seconds, I have to plan exactly and/or script out what I'm going to say on each slide, otherwise I'll certainly go over.  I scripted it.  Then I cut it.  Then I cut it again.  I could still cut it more.&lt;/li&gt;
&lt;li&gt;Limit the scope.  In six minutes, there's a limit to what an audience can digest.&lt;/li&gt;
&lt;li&gt;Limit the text on the slides.  This is good advice in general, but even more important in this style.&lt;/li&gt;
&lt;li&gt;I think it's a very, very good exercise.  I found that having the constraint was very useful; it definitely kept me focused and on topic.  &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;I'll definitely use this style again.  The presentation can be found at: &lt;a href=&quot;http://aetherical.com/presentations/web-2-0-people-conversations-and-community&quot;&gt;Into the Aether: Web 2.0 -- People, Conversations, and Community&lt;/a&gt;.&lt;/p&gt;
          </content>  </entry>
  <entry xml:base="http://aetherical.com/">
    <author>
      <name>Matt Williams</name>
    </author>
    <id>tag:aetherical.com,2008-05-20:69</id>
    <published>2008-05-20T20:46:00Z</published>
    <updated>2008-05-20T20:50:31Z</updated>
    <category term="blog"/>
    <category term="syndicated"/>
    <category term="paragdigm"/>
    <category term="philosophy"/>
    <category term="programming"/>
    <category term="ruby"/>
    <link href="http://aetherical.com/2008/5/20/dsl-or-magick" rel="alternate" type="text/html"/>
    <title>DSL or Magick?</title>
<content type="html">
            &lt;p&gt;While at &lt;a href=&quot;columbusrb.com&quot;&gt;Columbus Ruby Brigade&lt;/a&gt;'s meeting last night there was a question of what's magick, what's a dsl, and when are you using too much magick.&lt;/p&gt;
&lt;p&gt;I came up with the following:&lt;/p&gt;
&lt;blockquote&gt;
DSL's make code easier to &lt;em&gt;read&lt;/em&gt;.  Magick makes it easier to &lt;em&gt;write&lt;/em&gt; code.  In specific, Magick makes it easier for &lt;em&gt;good&lt;/em&gt; developers to write &lt;em&gt;better&lt;/em&gt; code; you still need to know what's going on.
&lt;/blockquote&gt;
&lt;p&gt;What do you think?&lt;/p&gt;
          </content>  </entry>
  <entry xml:base="http://aetherical.com/">
    <author>
      <name>Matt Williams</name>
    </author>
    <id>tag:aetherical.com,2008-05-14:68</id>
    <published>2008-05-14T15:39:00Z</published>
    <updated>2008-05-14T18:15:33Z</updated>
    <category term="blog"/>
    <category term="syndicated"/>
    <category term="metaprogramming"/>
    <category term="programming"/>
    <category term="ruby"/>
    <category term="scope"/>
    <link href="http://aetherical.com/2008/5/14/scope-kills" rel="alternate" type="text/html"/>
    <title>Scope Kills</title>
<summary type="html">I'm not talking about bad breath.  Rather, I'm talking about scope in ruby.</summary><content type="html">
            I'm not talking about bad breath.  Rather, I'm talking about scope in ruby.
&lt;p&gt;First off, I'm not talking about bad breath.  Rather, I'm talking about scope in ruby.&lt;/p&gt;
&lt;p&gt;The previous entry, &lt;a href=&quot;http://aetherical.com/2008/5/9/attributes-with-default-values-on-steroids&quot;&gt;attributes with default values (on steroids)&lt;/a&gt;, had an issue with it, due to the way in which ruby defines scope (as of 1.8, scope is supposed to change in 1.9).  Here's the &quot;broken&quot; code:&lt;/p&gt;
&lt;table class=&quot;CodeRay&quot;&gt;&lt;tr&gt;
  &lt;td title=&quot;click to toggle&quot; class=&quot;line_numbers&quot;&gt;&lt;pre&gt;1&lt;tt&gt;
&lt;/tt&gt;2&lt;tt&gt;
&lt;/tt&gt;3&lt;tt&gt;
&lt;/tt&gt;4&lt;tt&gt;
&lt;/tt&gt;&lt;strong&gt;5&lt;/strong&gt;&lt;tt&gt;
&lt;/tt&gt;6&lt;tt&gt;
&lt;/tt&gt;7&lt;tt&gt;
&lt;/tt&gt;8&lt;tt&gt;
&lt;/tt&gt;9&lt;tt&gt;
&lt;/tt&gt;&lt;strong&gt;10&lt;/strong&gt;&lt;tt&gt;
&lt;/tt&gt;11&lt;tt&gt;
&lt;/tt&gt;12&lt;tt&gt;
&lt;/tt&gt;13&lt;tt&gt;
&lt;/tt&gt;14&lt;tt&gt;
&lt;/tt&gt;&lt;strong&gt;15&lt;/strong&gt;&lt;tt&gt;
&lt;/tt&gt;16&lt;tt&gt;
&lt;/tt&gt;17&lt;tt&gt;
&lt;/tt&gt;18&lt;tt&gt;
&lt;/tt&gt;19&lt;tt&gt;
&lt;/tt&gt;&lt;strong&gt;20&lt;/strong&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;/pre&gt;&lt;/td&gt;
  &lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;span class=&quot;r&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;cl&quot;&gt;Object&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;  &lt;span class=&quot;r&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;pc&quot;&gt;self&lt;/span&gt;.attribute(*arg,&amp;amp;block)&lt;tt&gt;
&lt;/tt&gt;    (name,value) = arg&lt;tt&gt;
&lt;/tt&gt;    &lt;span class=&quot;pc&quot;&gt;self&lt;/span&gt;.send(&lt;span class=&quot;sy&quot;&gt;:define_method&lt;/span&gt;, name) {&lt;tt&gt;
&lt;/tt&gt;      &lt;span class=&quot;r&quot;&gt;if&lt;/span&gt; instance_variables.include? &lt;span class=&quot;s&quot;&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;@&lt;/span&gt;&lt;span class=&quot;il&quot;&gt;&lt;span class=&quot;dl&quot;&gt;#{&lt;/span&gt;name&lt;span class=&quot;dl&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;           &lt;span class=&quot;pc&quot;&gt;self&lt;/span&gt;.instance_eval &lt;span class=&quot;s&quot;&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;@&lt;/span&gt;&lt;span class=&quot;il&quot;&gt;&lt;span class=&quot;dl&quot;&gt;#{&lt;/span&gt;name&lt;span class=&quot;dl&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;      &lt;span class=&quot;r&quot;&gt;else&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;        &lt;span class=&quot;r&quot;&gt;if&lt;/span&gt; block_given?&lt;tt&gt;
&lt;/tt&gt;          instance_eval &amp;amp;block&lt;tt&gt;
&lt;/tt&gt;        &lt;span class=&quot;r&quot;&gt;else&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;          value&lt;tt&gt;
&lt;/tt&gt;        &lt;span class=&quot;r&quot;&gt;end&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;      &lt;span class=&quot;r&quot;&gt;end&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;    }&lt;tt&gt;
&lt;/tt&gt;    &lt;span class=&quot;pc&quot;&gt;self&lt;/span&gt;.send(&lt;span class=&quot;sy&quot;&gt;:define_method&lt;/span&gt;, &lt;span class=&quot;s&quot;&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;il&quot;&gt;&lt;span class=&quot;dl&quot;&gt;#{&lt;/span&gt;name&lt;span class=&quot;dl&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;){ |value|&lt;tt&gt;
&lt;/tt&gt;      &lt;span class=&quot;pc&quot;&gt;self&lt;/span&gt;.instance_eval &lt;span class=&quot;s&quot;&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;@&lt;/span&gt;&lt;span class=&quot;il&quot;&gt;&lt;span class=&quot;dl&quot;&gt;#{&lt;/span&gt;name&lt;span class=&quot;dl&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt; = value&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;    }&lt;tt&gt;
&lt;/tt&gt;  &lt;span class=&quot;r&quot;&gt;end&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;span class=&quot;r&quot;&gt;end&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;/tr&gt;&lt;/table&gt;

&lt;p&gt;The problem is with the &lt;code&gt;value&lt;/code&gt; variable.  Because it is set within the &lt;code&gt;Object#attribute&lt;code&gt; method, the reference to value is the same throughout the entire method.  So, when we change value, by setting it in the &quot;setter&quot; method, we are changing it for every instance of the variable.  In addition, since we're setting it at the class level, any object which belongs to the class for which we are setting it has the same value.  The solution is pretty simple:&lt;/p&gt;
&lt;table class=&quot;CodeRay&quot;&gt;&lt;tr&gt;
  &lt;td title=&quot;click to toggle&quot; class=&quot;line_numbers&quot;&gt;&lt;pre&gt;1&lt;tt&gt;
&lt;/tt&gt;2&lt;tt&gt;
&lt;/tt&gt;3&lt;tt&gt;
&lt;/tt&gt;4&lt;tt&gt;
&lt;/tt&gt;&lt;strong&gt;5&lt;/strong&gt;&lt;tt&gt;
&lt;/tt&gt;6&lt;tt&gt;
&lt;/tt&gt;7&lt;tt&gt;
&lt;/tt&gt;8&lt;tt&gt;
&lt;/tt&gt;9&lt;tt&gt;
&lt;/tt&gt;&lt;strong&gt;10&lt;/strong&gt;&lt;tt&gt;
&lt;/tt&gt;11&lt;tt&gt;
&lt;/tt&gt;12&lt;tt&gt;
&lt;/tt&gt;13&lt;tt&gt;
&lt;/tt&gt;14&lt;tt&gt;
&lt;/tt&gt;&lt;strong&gt;15&lt;/strong&gt;&lt;tt&gt;
&lt;/tt&gt;16&lt;tt&gt;
&lt;/tt&gt;17&lt;tt&gt;
&lt;/tt&gt;18&lt;tt&gt;
&lt;/tt&gt;19&lt;tt&gt;
&lt;/tt&gt;&lt;/pre&gt;&lt;/td&gt;
  &lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;span class=&quot;r&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;pc&quot;&gt;self&lt;/span&gt;.attribute(*arg,&amp;amp;block)&lt;tt&gt;
&lt;/tt&gt;    (name, default) = arg&lt;tt&gt;
&lt;/tt&gt;    &lt;span class=&quot;pc&quot;&gt;self&lt;/span&gt;.send(&lt;span class=&quot;sy&quot;&gt;:define_method&lt;/span&gt;, name) {&lt;tt&gt;
&lt;/tt&gt;      &lt;span class=&quot;r&quot;&gt;if&lt;/span&gt; instance_variables.include? &lt;span class=&quot;s&quot;&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;@&lt;/span&gt;&lt;span class=&quot;il&quot;&gt;&lt;span class=&quot;dl&quot;&gt;#{&lt;/span&gt;name&lt;span class=&quot;dl&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;           &lt;span class=&quot;pc&quot;&gt;self&lt;/span&gt;.instance_eval &lt;span class=&quot;s&quot;&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;@&lt;/span&gt;&lt;span class=&quot;il&quot;&gt;&lt;span class=&quot;dl&quot;&gt;#{&lt;/span&gt;name&lt;span class=&quot;dl&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;      &lt;span class=&quot;r&quot;&gt;else&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;        &lt;span class=&quot;r&quot;&gt;if&lt;/span&gt; block_given?&lt;tt&gt;
&lt;/tt&gt;          instance_eval &amp;amp;block&lt;tt&gt;
&lt;/tt&gt;        &lt;span class=&quot;r&quot;&gt;else&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;          default&lt;tt&gt;
&lt;/tt&gt;        &lt;span class=&quot;r&quot;&gt;end&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;      &lt;span class=&quot;r&quot;&gt;end&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;    }&lt;tt&gt;
&lt;/tt&gt;    &lt;span class=&quot;pc&quot;&gt;self&lt;/span&gt;.send(&lt;span class=&quot;sy&quot;&gt;:define_method&lt;/span&gt;, &lt;span class=&quot;s&quot;&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;il&quot;&gt;&lt;span class=&quot;dl&quot;&gt;#{&lt;/span&gt;name&lt;span class=&quot;dl&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;){ |value|&lt;tt&gt;
&lt;/tt&gt;      &lt;span class=&quot;pc&quot;&gt;self&lt;/span&gt;.instance_eval &lt;span class=&quot;s&quot;&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;@&lt;/span&gt;&lt;span class=&quot;il&quot;&gt;&lt;span class=&quot;dl&quot;&gt;#{&lt;/span&gt;name&lt;span class=&quot;dl&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt; = value&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;    }&lt;tt&gt;
&lt;/tt&gt;  &lt;span class=&quot;r&quot;&gt;end&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;span class=&quot;r&quot;&gt;end&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;/tr&gt;&lt;/table&gt;

&lt;p&gt;Notice that I'm using &lt;code&gt;default&lt;/code&gt; now within the accessor method.  This removes the issue with value, and it now works properly.&lt;/p&gt;
          </content>  </entry>
  <entry xml:base="http://aetherical.com/">
    <author>
      <name>Matt Williams</name>
    </author>
    <id>tag:aetherical.com,2008-05-09:62</id>
    <published>2008-05-09T04:17:00Z</published>
    <updated>2008-05-14T18:17:19Z</updated>
    <category term="blog"/>
    <category term="syndicated"/>
    <category term="metaprogramming"/>
    <category term="programming"/>
    <category term="ruby"/>
    <link href="http://aetherical.com/2008/5/9/attributes-with-default-values-on-steroids" rel="alternate" type="text/html"/>
    <title>attributes with default values (on steroids)</title>
<content type="html">
            &lt;p&gt;&lt;b&gt;EDITED to fix bug:&lt;/b&gt; See &lt;a href=&quot;http://aetherical.com/2008/5/14/scope-kills&quot;&gt;Scope Kills&lt;/a&gt; for details.&lt;/p&gt;
&lt;p&gt;While ruby has &lt;code&gt;attr_accessor&lt;/code&gt; there's no good way to specify a default value which comes as part of the stock language.  Thank goodness for metaprogramming.  Based off of &lt;a href=&quot;http://www.railsonwave.com/railsonwave/2008/4/15/create-getter-and-setter-on-a-valorized-variable&quot;&gt;Create getter and setter on a valorized variable&lt;/a&gt;, I have a solution which takes either a value or a block as the default.  It's based, in part, upon my solution for Ruby Quiz #67 &lt;a href=&quot;http://www.rubyquiz.com/quiz67.html&quot;&gt;Metakoans&lt;/a&gt;.&lt;/p&gt;
&lt;table class=&quot;CodeRay&quot;&gt;&lt;tr&gt;
  &lt;td title=&quot;click to toggle&quot; class=&quot;line_numbers&quot;&gt;&lt;pre&gt;1&lt;tt&gt;
&lt;/tt&gt;2&lt;tt&gt;
&lt;/tt&gt;3&lt;tt&gt;
&lt;/tt&gt;4&lt;tt&gt;
&lt;/tt&gt;&lt;strong&gt;5&lt;/strong&gt;&lt;tt&gt;
&lt;/tt&gt;6&lt;tt&gt;
&lt;/tt&gt;7&lt;tt&gt;
&lt;/tt&gt;8&lt;tt&gt;
&lt;/tt&gt;9&lt;tt&gt;
&lt;/tt&gt;&lt;strong&gt;10&lt;/strong&gt;&lt;tt&gt;
&lt;/tt&gt;11&lt;tt&gt;
&lt;/tt&gt;12&lt;tt&gt;
&lt;/tt&gt;13&lt;tt&gt;
&lt;/tt&gt;14&lt;tt&gt;
&lt;/tt&gt;&lt;strong&gt;15&lt;/strong&gt;&lt;tt&gt;
&lt;/tt&gt;16&lt;tt&gt;
&lt;/tt&gt;17&lt;tt&gt;
&lt;/tt&gt;18&lt;tt&gt;
&lt;/tt&gt;19&lt;tt&gt;
&lt;/tt&gt;&lt;strong&gt;20&lt;/strong&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;/pre&gt;&lt;/td&gt;
  &lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;span class=&quot;r&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;cl&quot;&gt;Object&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;  &lt;span class=&quot;r&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;pc&quot;&gt;self&lt;/span&gt;.attribute(*arg,&amp;amp;block)&lt;tt&gt;
&lt;/tt&gt;    (name,default) = arg&lt;tt&gt;
&lt;/tt&gt;    &lt;span class=&quot;pc&quot;&gt;self&lt;/span&gt;.send(&lt;span class=&quot;sy&quot;&gt;:define_method&lt;/span&gt;, name) {&lt;tt&gt;
&lt;/tt&gt;      &lt;span class=&quot;r&quot;&gt;if&lt;/span&gt; instance_variables.include? &lt;span class=&quot;s&quot;&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;@&lt;/span&gt;&lt;span class=&quot;il&quot;&gt;&lt;span class=&quot;dl&quot;&gt;#{&lt;/span&gt;name&lt;span class=&quot;dl&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;           &lt;span class=&quot;pc&quot;&gt;self&lt;/span&gt;.instance_eval &lt;span class=&quot;s&quot;&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;@&lt;/span&gt;&lt;span class=&quot;il&quot;&gt;&lt;span class=&quot;dl&quot;&gt;#{&lt;/span&gt;name&lt;span class=&quot;dl&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;      &lt;span class=&quot;r&quot;&gt;else&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;        &lt;span class=&quot;r&quot;&gt;if&lt;/span&gt; block_given?&lt;tt&gt;
&lt;/tt&gt;          instance_eval &amp;amp;block&lt;tt&gt;
&lt;/tt&gt;        &lt;span class=&quot;r&quot;&gt;else&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;          default&lt;tt&gt;
&lt;/tt&gt;        &lt;span class=&quot;r&quot;&gt;end&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;      &lt;span class=&quot;r&quot;&gt;end&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;    }&lt;tt&gt;
&lt;/tt&gt;    &lt;span class=&quot;pc&quot;&gt;self&lt;/span&gt;.send(&lt;span class=&quot;sy&quot;&gt;:define_method&lt;/span&gt;, &lt;span class=&quot;s&quot;&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;il&quot;&gt;&lt;span class=&quot;dl&quot;&gt;#{&lt;/span&gt;name&lt;span class=&quot;dl&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;){ |value|&lt;tt&gt;
&lt;/tt&gt;      &lt;span class=&quot;pc&quot;&gt;self&lt;/span&gt;.instance_eval &lt;span class=&quot;s&quot;&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;@&lt;/span&gt;&lt;span class=&quot;il&quot;&gt;&lt;span class=&quot;dl&quot;&gt;#{&lt;/span&gt;name&lt;span class=&quot;dl&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt; = value&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;    }&lt;tt&gt;
&lt;/tt&gt;  &lt;span class=&quot;r&quot;&gt;end&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;span class=&quot;r&quot;&gt;end&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;/tr&gt;&lt;/table&gt;

&lt;p&gt;Given the following class:&lt;/p&gt;
&lt;table class=&quot;CodeRay&quot;&gt;&lt;tr&gt;
  &lt;td title=&quot;click to toggle&quot; class=&quot;line_numbers&quot;&gt;&lt;pre&gt;1&lt;tt&gt;
&lt;/tt&gt;2&lt;tt&gt;
&lt;/tt&gt;3&lt;tt&gt;
&lt;/tt&gt;4&lt;tt&gt;
&lt;/tt&gt;&lt;strong&gt;5&lt;/strong&gt;&lt;tt&gt;
&lt;/tt&gt;6&lt;tt&gt;
&lt;/tt&gt;&lt;/pre&gt;&lt;/td&gt;
  &lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;span class=&quot;r&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;cl&quot;&gt;Foo&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;  attribute &lt;span class=&quot;sy&quot;&gt;:bar&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;  attribute(&lt;span class=&quot;sy&quot;&gt;:fud&lt;/span&gt;) {instance_variables.include?(&lt;span class=&quot;s&quot;&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;@bar&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;) ? &lt;span class=&quot;iv&quot;&gt;@bar&lt;/span&gt; : &lt;span class=&quot;s&quot;&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;k&quot;&gt; &lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;/span&gt;}&lt;tt&gt;
&lt;/tt&gt;  attribute &lt;span class=&quot;sy&quot;&gt;:fi&lt;/span&gt;, &lt;span class=&quot;i&quot;&gt;10&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;span class=&quot;r&quot;&gt;end&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;/tr&gt;&lt;/table&gt;

&lt;p&gt;we can test as follows:&lt;/p&gt;
&lt;table class=&quot;CodeRay&quot;&gt;&lt;tr&gt;
  &lt;td title=&quot;click to toggle&quot; class=&quot;line_numbers&quot;&gt;&lt;pre&gt;1&lt;tt&gt;
&lt;/tt&gt;2&lt;tt&gt;
&lt;/tt&gt;3&lt;tt&gt;
&lt;/tt&gt;4&lt;tt&gt;
&lt;/tt&gt;&lt;strong&gt;5&lt;/strong&gt;&lt;tt&gt;
&lt;/tt&gt;6&lt;tt&gt;
&lt;/tt&gt;7&lt;tt&gt;
&lt;/tt&gt;8&lt;tt&gt;
&lt;/tt&gt;9&lt;tt&gt;
&lt;/tt&gt;&lt;strong&gt;10&lt;/strong&gt;&lt;tt&gt;
&lt;/tt&gt;11&lt;tt&gt;
&lt;/tt&gt;12&lt;tt&gt;
&lt;/tt&gt;13&lt;tt&gt;
&lt;/tt&gt;14&lt;tt&gt;
&lt;/tt&gt;&lt;strong&gt;15&lt;/strong&gt;&lt;tt&gt;
&lt;/tt&gt;16&lt;tt&gt;
&lt;/tt&gt;17&lt;tt&gt;
&lt;/tt&gt;18&lt;tt&gt;
&lt;/tt&gt;&lt;/pre&gt;&lt;/td&gt;
  &lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;tt&gt;
&lt;/tt&gt;&amp;gt;&amp;gt;   t=&lt;span class=&quot;co&quot;&gt;Foo&lt;/span&gt;.new&lt;tt&gt;
&lt;/tt&gt;=&amp;gt; &lt;span class=&quot;c&quot;&gt;#&amp;lt;Foo:0xb7b9cadc&amp;gt;&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;&amp;gt;&amp;gt; t.bar&lt;tt&gt;
&lt;/tt&gt;=&amp;gt; &lt;span class=&quot;pc&quot;&gt;nil&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;&amp;gt;&amp;gt; t.fud&lt;tt&gt;
&lt;/tt&gt;=&amp;gt; &lt;span class=&quot;s&quot;&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt; &lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;&amp;gt;&amp;gt; t.fi&lt;tt&gt;
&lt;/tt&gt;=&amp;gt; &lt;span class=&quot;i&quot;&gt;10&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;&amp;gt;&amp;gt; t.bar = &lt;span class=&quot;i&quot;&gt;5&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;=&amp;gt; &lt;span class=&quot;i&quot;&gt;5&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;&amp;gt;&amp;gt; t.fud&lt;tt&gt;
&lt;/tt&gt;=&amp;gt; &lt;span class=&quot;i&quot;&gt;5&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;&amp;gt;&amp;gt; t.fud = &lt;span class=&quot;i&quot;&gt;20&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;=&amp;gt; &lt;span class=&quot;i&quot;&gt;20&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;&amp;gt;&amp;gt; t.fud&lt;tt&gt;
&lt;/tt&gt;=&amp;gt; &lt;span class=&quot;i&quot;&gt;20&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;&amp;gt;&amp;gt; &lt;tt&gt;
&lt;/tt&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;/tr&gt;&lt;/table&gt;

&lt;p&gt;I imagine it can be simplified some more, but it works, and I think it's kinda nifty.....&lt;/p&gt;
          </content>  </entry>
  <entry xml:base="http://aetherical.com/">
    <author>
      <name>Matt Williams</name>
    </author>
    <id>tag:aetherical.com,2008-05-07:61</id>
    <published>2008-05-07T21:07:00Z</published>
    <updated>2008-05-07T21:32:23Z</updated>
    <category term="blog"/>
    <category term="syndicated"/>
    <category term="metaprogramming"/>
    <category term="parser"/>
    <category term="ruby"/>
    <category term="treetop"/>
    <category term="war"/>
    <link href="http://aetherical.com/2008/5/7/a-view-from-the-treetops-creating-parser-grammars-on-the-fly" rel="alternate" type="text/html"/>
    <title>A view from the Treetops: Creating parser grammars on the fly</title>
<content type="html">
            &lt;p&gt;&lt;a href=&quot;http://treetop.rubyforge.org/&quot;&gt;Treetop&lt;/a&gt; is, as they say on their website, &lt;em&gt;... a language for describing languages. Combining the elegance of Ruby with cutting-edge parsing expression grammars, it helps you analyze syntax with revolutionarily ease.&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;In working on my game library, I've been experimenting with Treetop for parsing user input.  At some point I am wanting to say: &lt;code&gt;create Militia of size 100&lt;/code&gt;.  In order to do this, I'd use a syntax like this (contrived):&lt;/p&gt;
&lt;table class=&quot;CodeRay&quot;&gt;&lt;tr&gt;
  &lt;td title=&quot;click to toggle&quot; class=&quot;line_numbers&quot;&gt;&lt;pre&gt;1&lt;tt&gt;
&lt;/tt&gt;2&lt;tt&gt;
&lt;/tt&gt;3&lt;tt&gt;
&lt;/tt&gt;4&lt;tt&gt;
&lt;/tt&gt;&lt;strong&gt;5&lt;/strong&gt;&lt;tt&gt;
&lt;/tt&gt;6&lt;tt&gt;
&lt;/tt&gt;7&lt;tt&gt;
&lt;/tt&gt;8&lt;tt&gt;
&lt;/tt&gt;9&lt;tt&gt;
&lt;/tt&gt;&lt;strong&gt;10&lt;/strong&gt;&lt;tt&gt;
&lt;/tt&gt;11&lt;tt&gt;
&lt;/tt&gt;12&lt;tt&gt;
&lt;/tt&gt;&lt;/pre&gt;&lt;/td&gt;
  &lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;tt&gt;
&lt;/tt&gt;grammar &lt;span class=&quot;co&quot;&gt;CreateUnit&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;  rule create_unit&lt;tt&gt;
&lt;/tt&gt;     &lt;span class=&quot;s&quot;&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;create &lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt; unit_type &lt;span class=&quot;s&quot;&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt; of size &lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt; number&lt;tt&gt;
&lt;/tt&gt;  &lt;span class=&quot;r&quot;&gt;end&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;  rule number&lt;tt&gt;
&lt;/tt&gt;    ([&lt;span class=&quot;i&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;i&quot;&gt;-9&lt;/span&gt;] [&lt;span class=&quot;i&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;i&quot;&gt;-9&lt;/span&gt;]* &lt;span class=&quot;rx&quot;&gt;&lt;span class=&quot;dl&quot;&gt;/&lt;/span&gt;&lt;span class=&quot;k&quot;&gt; '0')&lt;tt&gt;
&lt;/tt&gt;  end&lt;tt&gt;
&lt;/tt&gt;  rule unit_type&lt;tt&gt;
&lt;/tt&gt;    [A-Z][a-z]&lt;tt&gt;
&lt;/tt&gt;  end&lt;tt&gt;
&lt;/tt&gt;end&lt;tt&gt;
&lt;/tt&gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;/tr&gt;&lt;/table&gt;

&lt;p&gt;Pretty simple rule, eh?  There's one problem:  my rule for &lt;code&gt;unit_type&lt;/code&gt; will allow us to use unit types which don't actually exist.  And since the unit types are defined at runtime by a yaml file (for information on how we're doing this see &lt;a href=&quot;http://aetherical.com/2008/4/25/classes-on-the-fly&quot;&gt;Classes on the Fly&lt;/a&gt;), we can't rightly say what we're going to use for our unit types ahead of time.  Nor is Treetop set up very well for defining parsers on the fly -- it can read from files at runtime, but it can't without having to go to the filesystem.  Hence this addition:&lt;/p&gt;
&lt;table class=&quot;CodeRay&quot;&gt;&lt;tr&gt;
  &lt;td title=&quot;click to toggle&quot; class=&quot;line_numbers&quot;&gt;&lt;pre&gt;1&lt;tt&gt;
&lt;/tt&gt;2&lt;tt&gt;
&lt;/tt&gt;3&lt;tt&gt;
&lt;/tt&gt;4&lt;tt&gt;
&lt;/tt&gt;&lt;strong&gt;5&lt;/strong&gt;&lt;tt&gt;
&lt;/tt&gt;6&lt;tt&gt;
&lt;/tt&gt;7&lt;tt&gt;
&lt;/tt&gt;8&lt;tt&gt;
&lt;/tt&gt;9&lt;tt&gt;
&lt;/tt&gt;&lt;strong&gt;10&lt;/strong&gt;&lt;tt&gt;
&lt;/tt&gt;11&lt;tt&gt;
&lt;/tt&gt;12&lt;tt&gt;
&lt;/tt&gt;13&lt;tt&gt;
&lt;/tt&gt;14&lt;tt&gt;
&lt;/tt&gt;&lt;strong&gt;15&lt;/strong&gt;&lt;tt&gt;
&lt;/tt&gt;16&lt;tt&gt;
&lt;/tt&gt;17&lt;tt&gt;
&lt;/tt&gt;18&lt;tt&gt;
&lt;/tt&gt;19&lt;tt&gt;
&lt;/tt&gt;&lt;/pre&gt;&lt;/td&gt;
  &lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;span class=&quot;r&quot;&gt;module&lt;/span&gt; &lt;span class=&quot;cl&quot;&gt;Treetop&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;  &lt;span class=&quot;r&quot;&gt;module&lt;/span&gt; &lt;span class=&quot;cl&quot;&gt;Compiler&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;    &lt;span class=&quot;r&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;cl&quot;&gt;GrammarCompiler&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;      &lt;span class=&quot;r&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;fu&quot;&gt;ruby_string&lt;/span&gt;(s)&lt;tt&gt;
&lt;/tt&gt;        parser = &lt;span class=&quot;co&quot;&gt;MetagrammarParser&lt;/span&gt;.new&lt;tt&gt;
&lt;/tt&gt;        result = parser.parse(s)&lt;tt&gt;
&lt;/tt&gt;        &lt;span class=&quot;r&quot;&gt;unless&lt;/span&gt; result&lt;tt&gt;
&lt;/tt&gt;          raise &lt;span class=&quot;co&quot;&gt;RuntimeError&lt;/span&gt;.new(parser.failure_reason)&lt;tt&gt;
&lt;/tt&gt;        &lt;span class=&quot;r&quot;&gt;end&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;        result.compile&lt;tt&gt;
&lt;/tt&gt;      &lt;span class=&quot;r&quot;&gt;end&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;    &lt;span class=&quot;r&quot;&gt;end&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;  &lt;span class=&quot;r&quot;&gt;end&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;  &lt;span class=&quot;r&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;pc&quot;&gt;self&lt;/span&gt;.compile_string(s)&lt;tt&gt;
&lt;/tt&gt;    compiler = &lt;span class=&quot;co&quot;&gt;Treetop&lt;/span&gt;::&lt;span class=&quot;co&quot;&gt;Compiler&lt;/span&gt;::&lt;span class=&quot;co&quot;&gt;GrammarCompiler&lt;/span&gt;.new&lt;tt&gt;
&lt;/tt&gt;    &lt;span class=&quot;co&quot;&gt;Object&lt;/span&gt;.class_eval(compiler.ruby_string(s))&lt;tt&gt;
&lt;/tt&gt;  &lt;span class=&quot;r&quot;&gt;end&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;span class=&quot;r&quot;&gt;end&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;/tr&gt;&lt;/table&gt;

&lt;p&gt;To use it, we'd do something like this:&lt;/p&gt;
&lt;table class=&quot;CodeRay&quot;&gt;&lt;tr&gt;
  &lt;td title=&quot;click to toggle&quot; class=&quot;line_numbers&quot;&gt;&lt;pre&gt;1&lt;tt&gt;
&lt;/tt&gt;2&lt;tt&gt;
&lt;/tt&gt;3&lt;tt&gt;
&lt;/tt&gt;4&lt;tt&gt;
&lt;/tt&gt;&lt;strong&gt;5&lt;/strong&gt;&lt;tt&gt;
&lt;/tt&gt;6&lt;tt&gt;
&lt;/tt&gt;7&lt;tt&gt;
&lt;/tt&gt;8&lt;tt&gt;
&lt;/tt&gt;9&lt;tt&gt;
&lt;/tt&gt;&lt;strong&gt;10&lt;/strong&gt;&lt;tt&gt;
&lt;/tt&gt;11&lt;tt&gt;
&lt;/tt&gt;12&lt;tt&gt;
&lt;/tt&gt;13&lt;tt&gt;
&lt;/tt&gt;14&lt;tt&gt;
&lt;/tt&gt;&lt;strong&gt;15&lt;/strong&gt;&lt;tt&gt;
&lt;/tt&gt;16&lt;tt&gt;
&lt;/tt&gt;17&lt;tt&gt;
&lt;/tt&gt;18&lt;tt&gt;
&lt;/tt&gt;19&lt;tt&gt;
&lt;/tt&gt;&lt;strong&gt;20&lt;/strong&gt;&lt;tt&gt;
&lt;/tt&gt;21&lt;tt&gt;
&lt;/tt&gt;22&lt;tt&gt;
&lt;/tt&gt;23&lt;tt&gt;
&lt;/tt&gt;24&lt;tt&gt;
&lt;/tt&gt;&lt;strong&gt;25&lt;/strong&gt;&lt;tt&gt;
&lt;/tt&gt;26&lt;tt&gt;
&lt;/tt&gt;27&lt;tt&gt;
&lt;/tt&gt;28&lt;tt&gt;
&lt;/tt&gt;29&lt;tt&gt;
&lt;/tt&gt;&lt;strong&gt;30&lt;/strong&gt;&lt;tt&gt;
&lt;/tt&gt;31&lt;tt&gt;
&lt;/tt&gt;32&lt;tt&gt;
&lt;/tt&gt;33&lt;tt&gt;
&lt;/tt&gt;34&lt;tt&gt;
&lt;/tt&gt;&lt;/pre&gt;&lt;/td&gt;
  &lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;span class=&quot;er&quot;&gt;$&lt;/span&gt; irb&lt;tt&gt;
&lt;/tt&gt;&amp;gt;&amp;gt; require &lt;span class=&quot;s&quot;&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;rubygems&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;=&amp;gt; &lt;span class=&quot;pc&quot;&gt;false&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;&amp;gt;&amp;gt; require &lt;span class=&quot;s&quot;&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;war&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;=&amp;gt; &lt;span class=&quot;pc&quot;&gt;true&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;&amp;gt;&amp;gt; require &lt;span class=&quot;s&quot;&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;treetop&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;=&amp;gt; &lt;span class=&quot;pc&quot;&gt;false&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;&amp;gt;&amp;gt; &lt;span class=&quot;co&quot;&gt;War&lt;/span&gt;::&lt;span class=&quot;co&quot;&gt;Utils&lt;/span&gt;::&lt;span class=&quot;co&quot;&gt;Loader&lt;/span&gt;.load_classes(&lt;span class=&quot;s&quot;&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;../config/units.yml&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;,&lt;span class=&quot;co&quot;&gt;War&lt;/span&gt;::&lt;span class=&quot;co&quot;&gt;Unit&lt;/span&gt;)&lt;tt&gt;
&lt;/tt&gt;militia&lt;tt&gt;
&lt;/tt&gt;rifleman&lt;tt&gt;
&lt;/tt&gt;scout&lt;tt&gt;
&lt;/tt&gt;landship&lt;tt&gt;
&lt;/tt&gt;walker&lt;tt&gt;
&lt;/tt&gt;=&amp;gt; [{&lt;span class=&quot;s&quot;&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;=&amp;gt;&lt;span class=&quot;s&quot;&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;militia&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;, &lt;span class=&quot;s&quot;&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;template&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;=&amp;gt;&lt;span class=&quot;s&quot;&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;soldier&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;, &lt;span class=&quot;s&quot;&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;attributes&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;=&amp;gt;{&lt;span class=&quot;s&quot;&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;strength&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;=&amp;gt;&lt;span class=&quot;i&quot;&gt;50&lt;/span&gt;, &lt;span class=&quot;s&quot;&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;symbol&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;=&amp;gt;&lt;span class=&quot;s&quot;&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;m&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;, &lt;span class=&quot;s&quot;&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;cost&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;=&amp;gt;&lt;span class=&quot;i&quot;&gt;50&lt;/span&gt;, &lt;span class=&quot;s&quot;&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;defence&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;=&amp;gt;&lt;span class=&quot;i&quot;&gt;10&lt;/span&gt;, &lt;span class=&quot;s&quot;&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;attack&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;=&amp;gt;&lt;span class=&quot;i&quot;&gt;-10&lt;/span&gt;}}, {&lt;span class=&quot;s&quot;&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;=&amp;gt;&lt;span class=&quot;s&quot;&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;rifleman&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;, &lt;span class=&quot;s&quot;&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;template&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;=&amp;gt;&lt;span class=&quot;s&quot;&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;soldier&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;, &lt;span class=&quot;s&quot;&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;attributes&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;=&amp;gt;{&lt;span class=&quot;s&quot;&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;strength&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;=&amp;gt;&lt;span class=&quot;i&quot;&gt;100&lt;/span&gt;, &lt;span class=&quot;s&quot;&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;symbol&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;=&amp;gt;&lt;span class=&quot;s&quot;&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;r&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;, &lt;span class=&quot;s&quot;&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;cost&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;=&amp;gt;&lt;span class=&quot;i&quot;&gt;125&lt;/span&gt;, &lt;span class=&quot;s&quot;&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;defence&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;=&amp;gt;&lt;span class=&quot;i&quot;&gt;30&lt;/span&gt;, &lt;span class=&quot;s&quot;&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;attack&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;=&amp;gt;&lt;span class=&quot;i&quot;&gt;30&lt;/span&gt;}}, {&lt;span class=&quot;s&quot;&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;=&amp;gt;&lt;span class=&quot;s&quot;&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;scout&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;, &lt;span class=&quot;s&quot;&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;template&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;=&amp;gt;&lt;span class=&quot;s&quot;&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;scout&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;, &lt;span class=&quot;s&quot;&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;attributes&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;=&amp;gt;{&lt;span class=&quot;s&quot;&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;strength&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;=&amp;gt;&lt;span class=&quot;i&quot;&gt;20&lt;/span&gt;, &lt;span class=&quot;s&quot;&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;symbol&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;=&amp;gt;&lt;span class=&quot;s&quot;&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;s&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;, &lt;span class=&quot;s&quot;&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;cost&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;=&amp;gt;&lt;span class=&quot;i&quot;&gt;200&lt;/span&gt;, &lt;span class=&quot;s&quot;&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;defence&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;=&amp;gt;&lt;span class=&quot;i&quot;&gt;10&lt;/span&gt;, &lt;span class=&quot;s&quot;&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;attack&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;=&amp;gt;&lt;span class=&quot;i&quot;&gt;10&lt;/span&gt;}}, {&lt;span class=&quot;s&quot;&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;=&amp;gt;&lt;span class=&quot;s&quot;&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;landship&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;, &lt;span class=&quot;s&quot;&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;template&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;=&amp;gt;&lt;span class=&quot;s&quot;&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;tank&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;, &lt;span class=&quot;s&quot;&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;attributes&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;=&amp;gt;{&lt;span class=&quot;s&quot;&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;strength&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;=&amp;gt;&lt;span class=&quot;i&quot;&gt;1500&lt;/span&gt;, &lt;span class=&quot;s&quot;&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;symbol&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;=&amp;gt;&lt;span class=&quot;s&quot;&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;L&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;, &lt;span class=&quot;s&quot;&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;cost&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;=&amp;gt;&lt;span class=&quot;i&quot;&gt;2000&lt;/span&gt;, &lt;span class=&quot;s&quot;&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;defence&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;=&amp;gt;&lt;span class=&quot;i&quot;&gt;200&lt;/span&gt;, &lt;span class=&quot;s&quot;&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;attack&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;=&amp;gt;&lt;span class=&quot;i&quot;&gt;200&lt;/span&gt;}}, {&lt;span class=&quot;s&quot;&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;=&amp;gt;&lt;span class=&quot;s&quot;&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;walker&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;, &lt;span class=&quot;s&quot;&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;template&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;=&amp;gt;&lt;span class=&quot;s&quot;&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;tank&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;, &lt;span class=&quot;s&quot;&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;attributes&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;=&amp;gt;{&lt;span class=&quot;s&quot;&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;strength&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;=&amp;gt;&lt;span class=&quot;i&quot;&gt;500&lt;/span&gt;, &lt;span class=&quot;s&quot;&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;cost&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;=&amp;gt;&lt;span class=&quot;i&quot;&gt;1250&lt;/span&gt;, &lt;span class=&quot;s&quot;&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;symbol&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;=&amp;gt;&lt;span class=&quot;s&quot;&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;w&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;, &lt;span class=&quot;s&quot;&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;movement&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;=&amp;gt;&lt;span class=&quot;i&quot;&gt;2&lt;/span&gt;, &lt;span class=&quot;s&quot;&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;defence&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;=&amp;gt;&lt;span class=&quot;i&quot;&gt;100&lt;/span&gt;, &lt;span class=&quot;s&quot;&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;vision&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;=&amp;gt;&lt;span class=&quot;i&quot;&gt;2&lt;/span&gt;, &lt;span class=&quot;s&quot;&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;attack&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;=&amp;gt;&lt;span class=&quot;i&quot;&gt;100&lt;/span&gt;}}]&lt;tt&gt;
&lt;/tt&gt;&amp;gt;&amp;gt; s = &lt;span class=&quot;s&quot;&gt;&lt;span class=&quot;dl&quot;&gt;&amp;lt;&amp;lt;EOF&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&lt;span class=&quot;k&quot;&gt;&lt;tt&gt;
&lt;/tt&gt;grammar UnitType&lt;tt&gt;
&lt;/tt&gt;rule unit_type&lt;tt&gt;
&lt;/tt&gt;&lt;/span&gt;&lt;span class=&quot;il&quot;&gt;&lt;span class=&quot;dl&quot;&gt;#{&lt;/span&gt;&lt;span class=&quot;co&quot;&gt;War&lt;/span&gt;::&lt;span class=&quot;co&quot;&gt;Unit&lt;/span&gt;.subclasses.map{|c|&lt;span class=&quot;s&quot;&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;il&quot;&gt;&lt;span class=&quot;dl&quot;&gt;#{&lt;/span&gt;c.to_s&lt;span class=&quot;dl&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;}.join(&lt;span class=&quot;s&quot;&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt; / &lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;)&lt;span class=&quot;dl&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;&lt;tt&gt;
&lt;/tt&gt;end&lt;tt&gt;
&lt;/tt&gt;end&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&lt;tt&gt;
&lt;/tt&gt;EOF&lt;/span&gt;&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;=&amp;gt; &lt;span class=&quot;s&quot;&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;grammar UnitType&lt;/span&gt;&lt;span class=&quot;ch&quot;&gt;\n&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;rule unit_type&lt;/span&gt;&lt;span class=&quot;ch&quot;&gt;\n&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;'Walker' / 'Landship' / 'Scout' / 'Rifleman' / 'Militia'&lt;/span&gt;&lt;span class=&quot;ch&quot;&gt;\n&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;&lt;span class=&quot;ch&quot;&gt;\n&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;&lt;span class=&quot;ch&quot;&gt;\n&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;&amp;gt;&amp;gt; require &lt;span class=&quot;s&quot;&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;treetop_extensions&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;=&amp;gt; &lt;span class=&quot;pc&quot;&gt;true&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;&amp;gt;&amp;gt; &lt;span class=&quot;co&quot;&gt;Treetop&lt;/span&gt;.compile_string(s)&lt;tt&gt;
&lt;/tt&gt;=&amp;gt; &lt;span class=&quot;co&quot;&gt;UnitTypeParser&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;&amp;gt;&amp;gt; parser = &lt;span class=&quot;co&quot;&gt;UnitTypeParser&lt;/span&gt;.new&lt;tt&gt;
&lt;/tt&gt;=&amp;gt; &lt;span class=&quot;c&quot;&gt;#&amp;lt;UnitTypeParser:0xb76ee2c4 @consume_all_input=true&amp;gt;&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;&amp;gt;&amp;gt; parser.parse(&lt;span class=&quot;s&quot;&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;Foo&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;)&lt;tt&gt;
&lt;/tt&gt;=&amp;gt; &lt;span class=&quot;pc&quot;&gt;nil&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;&amp;gt;&amp;gt; parser.parse(&lt;span class=&quot;s&quot;&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;Militia&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;)&lt;tt&gt;
&lt;/tt&gt;=&amp;gt; &lt;span class=&quot;co&quot;&gt;SyntaxNode&lt;/span&gt; offset=&lt;span class=&quot;i&quot;&gt;0&lt;/span&gt;, &lt;span class=&quot;s&quot;&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;Militia&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;&amp;gt;&amp;gt; &lt;tt&gt;
&lt;/tt&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;/tr&gt;&lt;/table&gt;

&lt;p&gt;So, we can now parse unit types -- let's change our grammar now to reflect this:&lt;/p&gt;
&lt;table class=&quot;CodeRay&quot;&gt;&lt;tr&gt;
  &lt;td title=&quot;click to toggle&quot; class=&quot;line_numbers&quot;&gt;&lt;pre&gt;1&lt;tt&gt;
&lt;/tt&gt;2&lt;tt&gt;
&lt;/tt&gt;3&lt;tt&gt;
&lt;/tt&gt;4&lt;tt&gt;
&lt;/tt&gt;&lt;strong&gt;5&lt;/strong&gt;&lt;tt&gt;
&lt;/tt&gt;6&lt;tt&gt;
&lt;/tt&gt;7&lt;tt&gt;
&lt;/tt&gt;8&lt;tt&gt;
&lt;/tt&gt;9&lt;tt&gt;
&lt;/tt&gt;&lt;strong&gt;10&lt;/strong&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;/pre&gt;&lt;/td&gt;
  &lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;tt&gt;
&lt;/tt&gt;grammar &lt;span class=&quot;co&quot;&gt;CreateUnit&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;  include &lt;span class=&quot;co&quot;&gt;UnitType&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;  rule create_unit&lt;tt&gt;
&lt;/tt&gt;     &lt;span class=&quot;s&quot;&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;create &lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt; unit_type &lt;span class=&quot;s&quot;&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt; of size &lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt; number&lt;tt&gt;
&lt;/tt&gt;  &lt;span class=&quot;r&quot;&gt;end&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;  rule number&lt;tt&gt;
&lt;/tt&gt;    ([&lt;span class=&quot;i&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;i&quot;&gt;-9&lt;/span&gt;] [&lt;span class=&quot;i&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;i&quot;&gt;-9&lt;/span&gt;]* &lt;span class=&quot;rx&quot;&gt;&lt;span class=&quot;dl&quot;&gt;/&lt;/span&gt;&lt;span class=&quot;k&quot;&gt; '0')&lt;tt&gt;
&lt;/tt&gt;  end&lt;tt&gt;
&lt;/tt&gt;end&lt;tt&gt;
&lt;/tt&gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;/tr&gt;&lt;/table&gt;

&lt;p&gt;Let's see it in practice (assume everything's been loaded...):&lt;/p&gt;
&lt;table class=&quot;CodeRay&quot;&gt;&lt;tr&gt;
  &lt;td title=&quot;click to toggle&quot; class=&quot;line_numbers&quot;&gt;&lt;pre&gt;1&lt;tt&gt;
&lt;/tt&gt;2&lt;tt&gt;
&lt;/tt&gt;3&lt;tt&gt;
&lt;/tt&gt;4&lt;tt&gt;
&lt;/tt&gt;&lt;strong&gt;5&lt;/strong&gt;&lt;tt&gt;
&lt;/tt&gt;6&lt;tt&gt;
&lt;/tt&gt;7&lt;tt&gt;
&lt;/tt&gt;8&lt;tt&gt;
&lt;/tt&gt;9&lt;tt&gt;
&lt;/tt&gt;&lt;strong&gt;10&lt;/strong&gt;&lt;tt&gt;
&lt;/tt&gt;11&lt;tt&gt;
&lt;/tt&gt;12&lt;tt&gt;
&lt;/tt&gt;13&lt;tt&gt;
&lt;/tt&gt;14&lt;tt&gt;
&lt;/tt&gt;&lt;strong&gt;15&lt;/strong&gt;&lt;tt&gt;
&lt;/tt&gt;16&lt;tt&gt;
&lt;/tt&gt;&lt;/pre&gt;&lt;/td&gt;
  &lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;tt&gt;
&lt;/tt&gt;&amp;gt;&amp;gt; p = &lt;span class=&quot;co&quot;&gt;CreateUnitParser&lt;/span&gt;.new&lt;tt&gt;
&lt;/tt&gt;=&amp;gt; &lt;span class=&quot;c&quot;&gt;#&amp;lt;CreateUnitParser:0xb76c845c @consume_all_input=true&amp;gt;&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;&amp;gt;&amp;gt; p.parse(&lt;span class=&quot;s&quot;&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;create Militia of size 100&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;)&lt;tt&gt;
&lt;/tt&gt;=&amp;gt; &lt;span class=&quot;co&quot;&gt;SyntaxNode&lt;/span&gt;+&lt;span class=&quot;co&quot;&gt;CreateUnit0&lt;/span&gt; offset=&lt;span class=&quot;i&quot;&gt;0&lt;/span&gt;, &lt;span class=&quot;s&quot;&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;... Militia of size 100&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt; (number,unit_type):&lt;tt&gt;
&lt;/tt&gt;  &lt;span class=&quot;co&quot;&gt;SyntaxNode&lt;/span&gt; offset=&lt;span class=&quot;i&quot;&gt;0&lt;/span&gt;, &lt;span class=&quot;s&quot;&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;create &lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;  &lt;span class=&quot;co&quot;&gt;SyntaxNode&lt;/span&gt; offset=&lt;span class=&quot;i&quot;&gt;7&lt;/span&gt;, &lt;span class=&quot;s&quot;&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;Militia&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;  &lt;span class=&quot;co&quot;&gt;SyntaxNode&lt;/span&gt; offset=&lt;span class=&quot;i&quot;&gt;14&lt;/span&gt;, &lt;span class=&quot;s&quot;&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt; of size &lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;  &lt;span class=&quot;co&quot;&gt;SyntaxNode&lt;/span&gt;+&lt;span class=&quot;co&quot;&gt;Number0&lt;/span&gt; offset=&lt;span class=&quot;i&quot;&gt;23&lt;/span&gt;, &lt;span class=&quot;s&quot;&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;100&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;:&lt;tt&gt;
&lt;/tt&gt;    &lt;span class=&quot;co&quot;&gt;SyntaxNode&lt;/span&gt; offset=&lt;span class=&quot;i&quot;&gt;23&lt;/span&gt;, &lt;span class=&quot;s&quot;&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;    &lt;span class=&quot;co&quot;&gt;SyntaxNode&lt;/span&gt; offset=&lt;span class=&quot;i&quot;&gt;24&lt;/span&gt;, &lt;span class=&quot;s&quot;&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;00&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;:&lt;tt&gt;
&lt;/tt&gt;      &lt;span class=&quot;co&quot;&gt;SyntaxNode&lt;/span&gt; offset=&lt;span class=&quot;i&quot;&gt;24&lt;/span&gt;, &lt;span class=&quot;s&quot;&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;      &lt;span class=&quot;co&quot;&gt;SyntaxNode&lt;/span&gt; offset=&lt;span class=&quot;i&quot;&gt;25&lt;/span&gt;, &lt;span class=&quot;s&quot;&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;&amp;gt;&amp;gt; p.parse(&lt;span class=&quot;s&quot;&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;create Foo of size -1&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;)&lt;tt&gt;
&lt;/tt&gt;=&amp;gt; &lt;span class=&quot;pc&quot;&gt;nil&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;&amp;gt;&amp;gt; &lt;tt&gt;
&lt;/tt&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;/tr&gt;&lt;/table&gt;

&lt;p&gt;So, there you have it, we've created a parser grammar on the fly, which we can use....&lt;/p&gt;
          </content>  </entry>
  <entry xml:base="http://aetherical.com/">
    <author>
      <name>Matt Williams</name>
    </author>
    <id>tag:aetherical.com,2008-04-29:60</id>
    <published>2008-04-29T13:57:00Z</published>
    <updated>2008-04-29T15:50:39Z</updated>
    <category term="blog"/>
    <category term="syndicated"/>
    <category term="jep"/>
    <category term="just_enough_programming"/>
    <category term="philosophy"/>
    <category term="programming"/>
    <link href="http://aetherical.com/2008/4/29/the-hardest-thing" rel="alternate" type="text/html"/>
    <title>The hardest thing</title>
<content type="html">
            &lt;p&gt;The hardest thing to do while programming is not the programming itself.  It is the &quot;Not Programming&quot;.&lt;p&gt;
&lt;p&gt;That is to say, the hardest part is not adding feature #65353, which you're probably never going to use, but it makes the code ever so much more flexible.  It is the question of &quot;Why am I doing this?  Do I really need it now (or ever)?&quot; &lt;/p&gt;
&lt;p&gt;Lately I've very much been on a simplicity kick; looking around at a lot of projects around me and how they're &amp;lt;strike&gt;buzzword compliant&amp;lt;/strike&gt;over architected, I can't help but to think of all the ways in which people are prone to &lt;a href=&quot;http://dictionary.reference.com/cite.html?qh=creeping%20featuritis&amp;amp;ia=foldoc&quot;&gt;feeping creaturitis&lt;/a&gt; and &lt;a href=&quot;http://blog.mmmultiworks.com/2008/4/25/bigmac-programmer&quot;&gt;Big Mac&lt;/a&gt; Programming.  &lt;/p&gt;
&lt;p&gt;I think that there are several things which can help -- in fact, I've coined a phrase &quot;Just Enough Programming&quot; -- more about that will follow, but here are a few things to help with &quot;Not Programming&quot;:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;BDD and/or TDD, although I think that BDD is better about &lt;a href=&quot;http://blog.jayfields.com/2008/04/understanding-why.html&quot;&gt;understanding why&lt;/a&gt; we are doing something.&lt;/li&gt;
&lt;li&gt;DRY code&lt;/li&gt;
&lt;li&gt;Lighter frameworks -- ones which do not require as many lines of configuration as they do of code.  Infinite scalability is for imps and  &lt;a href=&quot;http://www.ietf.org/rfc/rfc2795.txt&quot;&gt;monkeys with typewriters&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;Declarative code -- it can be easier to limit ourselves this way (by the same token, do not fall into the trap of &lt;a href=&quot;http://en.wikipedia.org/wiki/Rococo&quot;&gt;Rococo&lt;/a&gt; Programming)
&lt;blockquote&gt;
A student once approached the master and asked, &quot;Does a Foo have the Bar nature?&quot;, to which the master replied &quot;Groo&quot; and returned to his meditations.
&lt;/blockquote&gt;&lt;/li&gt;
&lt;li&gt;Shorter integration cycles&lt;/li&gt;
&lt;/ul&gt;

Occam's Razor: &quot;Shaves as close as a blade or your money back&quot;.
          </content>  </entry>
  <entry xml:base="http://aetherical.com/">
    <author>
      <name>Matt Williams</name>
    </author>
    <id>tag:aetherical.com,2008-04-25:59</id>
    <published>2008-04-25T16:33:00Z</published>
    <updated>2008-04-25T17:06:19Z</updated>
    <category term="blog"/>
    <category term="syndicated"/>
    <category term="game"/>
    <category term="m3"/>
    <category term="metaprogramming"/>
    <category term="ruby"/>
    <category term="war"/>
    <link href="http://aetherical.com/2008/4/25/classes-on-the-fly" rel="alternate" type="text/html"/>
    <title>Classes on the Fly</title>
<summary type="html">I recently had a case (a game) where I had the potential for many classes which were similar, but have enough differences it made sense to dry them up, so I developed a method to  use yaml to define a class.</summary><content type="html">
            I recently had a case (a game) where I had the potential for many classes which were similar, but have enough differences it made sense to dry them up, so I developed a method to  use yaml to define a class.
&lt;p&gt;In my development of &lt;em&gt;Machines, Monsters, and Madness&lt;/em&gt;, I've taken what might be described as a side excursion: I'm documenting the process of creating a simple wargame in Ruby which encompasses a library of game related utilities which will make its way into M&lt;sup&gt;3&lt;/sup&gt;.&lt;/p&gt;
&lt;p&gt;As it turns out, there are many unit and terrain types.  These have a lot of overlap as well as there being many, many classes which would be needed.  So, I've come up with a way to dry up my code and use a yaml file for generating these classes.  With very little expansion, it could be used for a more generic solution (I'll get into that below).&lt;/p&gt;
&lt;p&gt;I start with _why's Creature class from DWEMTHY's array (&lt;a href=&quot;http://poignantguide.net/dwemthy/&quot;&gt;$$ DWEMTHY_S ARRAY ^!^ A RUBY MINI_DUNGEON ^!^ ONLY 60 LINES OF ...&lt;/a&gt;), but using the updated version from &lt;a href=&quot;http://whytheluckystiff.net/articles/seeingMetaclassesClearly.html&quot;&gt;Seeing Metaclasses Clearly&lt;/a&gt;, which uses a helper called &lt;code&gt;metaid.rb&lt;/code&gt; to encapsulate much of the meta-classiness:&lt;/p&gt;
&lt;table class=&quot;CodeRay&quot;&gt;&lt;tr&gt;
  &lt;td title=&quot;click to toggle&quot; class=&quot;line_numbers&quot;&gt;&lt;pre&gt;1&lt;tt&gt;
&lt;/tt&gt;2&lt;tt&gt;
&lt;/tt&gt;3&lt;tt&gt;
&lt;/tt&gt;4&lt;tt&gt;
&lt;/tt&gt;&lt;strong&gt;5&lt;/strong&gt;&lt;tt&gt;
&lt;/tt&gt;6&lt;tt&gt;
&lt;/tt&gt;7&lt;tt&gt;
&lt;/tt&gt;8&lt;tt&gt;
&lt;/tt&gt;9&lt;tt&gt;
&lt;/tt&gt;&lt;strong&gt;10&lt;/strong&gt;&lt;tt&gt;
&lt;/tt&gt;11&lt;tt&gt;
&lt;/tt&gt;12&lt;tt&gt;
&lt;/tt&gt;13&lt;tt&gt;
&lt;/tt&gt;14&lt;tt&gt;
&lt;/tt&gt;&lt;strong&gt;15&lt;/strong&gt;&lt;tt&gt;
&lt;/tt&gt;16&lt;tt&gt;
&lt;/tt&gt;&lt;/pre&gt;&lt;/td&gt;
  &lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;tt&gt;
&lt;/tt&gt; &lt;span class=&quot;r&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;cl&quot;&gt;Object&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;   &lt;span class=&quot;c&quot;&gt;# The hidden singleton lurks behind everyone&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;   &lt;span class=&quot;r&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;fu&quot;&gt;metaclass&lt;/span&gt;; &lt;span class=&quot;r&quot;&gt;class&lt;/span&gt; &amp;lt;&amp;lt; &lt;span class=&quot;cl&quot;&gt;self&lt;/span&gt;; &lt;span class=&quot;pc&quot;&gt;self&lt;/span&gt;; &lt;span class=&quot;r&quot;&gt;end&lt;/span&gt;; &lt;span class=&quot;r&quot;&gt;end&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;   &lt;span class=&quot;r&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;fu&quot;&gt;meta_eval&lt;/span&gt; &amp;amp;blk; metaclass.instance_eval &amp;amp;blk; &lt;span class=&quot;r&quot;&gt;end&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;tt&gt;
&lt;/tt&gt;   &lt;span class=&quot;c&quot;&gt;# Adds methods to a metaclass&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;   &lt;span class=&quot;r&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;fu&quot;&gt;meta_def&lt;/span&gt; name, &amp;amp;blk&lt;tt&gt;
&lt;/tt&gt;     meta_eval { define_method name, &amp;amp;blk }&lt;tt&gt;
&lt;/tt&gt;   &lt;span class=&quot;r&quot;&gt;end&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;tt&gt;
&lt;/tt&gt;   &lt;span class=&quot;c&quot;&gt;# Defines an instance method within a class&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;   &lt;span class=&quot;r&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;fu&quot;&gt;class_def&lt;/span&gt; name, &amp;amp;blk&lt;tt&gt;
&lt;/tt&gt;     class_eval { define_method name, &amp;amp;blk }&lt;tt&gt;
&lt;/tt&gt;   &lt;span class=&quot;r&quot;&gt;end&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt; &lt;span class=&quot;r&quot;&gt;end&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;/tr&gt;&lt;/table&gt;

&lt;p&gt;This leads to a modified version of &lt;code&gt;creature.rb&lt;/code&gt; which I am calling &lt;code&gt;traiter.rb&lt;/code&gt; (because it defines classes with traits, don'tcha know?):
&lt;table class=&quot;CodeRay&quot;&gt;&lt;tr&gt;
  &lt;td title=&quot;click to toggle&quot; class=&quot;line_numbers&quot;&gt;&lt;pre&gt;1&lt;tt&gt;
&lt;/tt&gt;2&lt;tt&gt;
&lt;/tt&gt;3&lt;tt&gt;
&lt;/tt&gt;4&lt;tt&gt;
&lt;/tt&gt;&lt;strong&gt;5&lt;/strong&gt;&lt;tt&gt;
&lt;/tt&gt;6&lt;tt&gt;
&lt;/tt&gt;7&lt;tt&gt;
&lt;/tt&gt;8&lt;tt&gt;
&lt;/tt&gt;9&lt;tt&gt;
&lt;/tt&gt;&lt;strong&gt;10&lt;/strong&gt;&lt;tt&gt;
&lt;/tt&gt;11&lt;tt&gt;
&lt;/tt&gt;12&lt;tt&gt;
&lt;/tt&gt;13&lt;tt&gt;
&lt;/tt&gt;14&lt;tt&gt;
&lt;/tt&gt;&lt;strong&gt;15&lt;/strong&gt;&lt;tt&gt;
&lt;/tt&gt;16&lt;tt&gt;
&lt;/tt&gt;&lt;/pre&gt;&lt;/td&gt;
  &lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;tt&gt;
&lt;/tt&gt; &lt;span class=&quot;r&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;cl&quot;&gt;Object&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;   &lt;span class=&quot;c&quot;&gt;# The hidden singleton lurks behind everyone&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;   &lt;span class=&quot;r&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;fu&quot;&gt;metaclass&lt;/span&gt;; &lt;span class=&quot;r&quot;&gt;class&lt;/span&gt; &amp;lt;&amp;lt; &lt;span class=&quot;cl&quot;&gt;self&lt;/span&gt;; &lt;span class=&quot;pc&quot;&gt;self&lt;/span&gt;; &lt;span class=&quot;r&quot;&gt;end&lt;/span&gt;; &lt;span class=&quot;r&quot;&gt;end&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;   &lt;span class=&quot;r&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;fu&quot;&gt;meta_eval&lt;/span&gt; &amp;amp;blk; metaclass.instance_eval &amp;amp;blk; &lt;span class=&quot;r&quot;&gt;end&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;tt&gt;
&lt;/tt&gt;   &lt;span class=&quot;c&quot;&gt;# Adds methods to a metaclass&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;   &lt;span class=&quot;r&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;fu&quot;&gt;meta_def&lt;/span&gt; name, &amp;amp;blk&lt;tt&gt;
&lt;/tt&gt;     meta_eval { define_method name, &amp;amp;blk }&lt;tt&gt;
&lt;/tt&gt;   &lt;span class=&quot;r&quot;&gt;end&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;tt&gt;
&lt;/tt&gt;   &lt;span class=&quot;c&quot;&gt;# Defines an instance method within a class&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;   &lt;span class=&quot;r&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;fu&quot;&gt;class_def&lt;/span&gt; name, &amp;amp;blk&lt;tt&gt;
&lt;/tt&gt;     class_eval { define_method name, &amp;amp;blk }&lt;tt&gt;
&lt;/tt&gt;   &lt;span class=&quot;r&quot;&gt;end&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt; &lt;span class=&quot;r&quot;&gt;end&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;/tr&gt;&lt;/table&gt;

&lt;p&gt;I've split this out from &lt;code&gt;&amp;lt;strike&gt;Creature&amp;lt;/strike&gt;Unit&lt;/code&gt;, because I will later use the same method to define terrain.  Then the &lt;code&gt;Unit&lt;/code&gt; follows:  &lt;/p&gt;
&lt;table class=&quot;CodeRay&quot;&gt;&lt;tr&gt;
  &lt;td title=&quot;click to toggle&quot; class=&quot;line_numbers&quot;&gt;&lt;pre&gt;1&lt;tt&gt;
&lt;/tt&gt;2&lt;tt&gt;
&lt;/tt&gt;3&lt;tt&gt;
&lt;/tt&gt;4&lt;tt&gt;
&lt;/tt&gt;&lt;strong&gt;5&lt;/strong&gt;&lt;tt&gt;
&lt;/tt&gt;6&lt;tt&gt;
&lt;/tt&gt;7&lt;tt&gt;
&lt;/tt&gt;8&lt;tt&gt;
&lt;/tt&gt;9&lt;tt&gt;
&lt;/tt&gt;&lt;strong&gt;10&lt;/strong&gt;&lt;tt&gt;
&lt;/tt&gt;11&lt;tt&gt;
&lt;/tt&gt;12&lt;tt&gt;
&lt;/tt&gt;13&lt;tt&gt;
&lt;/tt&gt;14&lt;tt&gt;
&lt;/tt&gt;&lt;strong&gt;15&lt;/strong&gt;&lt;tt&gt;
&lt;/tt&gt;16&lt;tt&gt;
&lt;/tt&gt;17&lt;tt&gt;
&lt;/tt&gt;18&lt;tt&gt;
&lt;/tt&gt;19&lt;tt&gt;
&lt;/tt&gt;&lt;strong&gt;20&lt;/strong&gt;&lt;tt&gt;
&lt;/tt&gt;21&lt;tt&gt;
&lt;/tt&gt;&lt;/pre&gt;&lt;/td&gt;
  &lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;tt&gt;
&lt;/tt&gt;require &lt;span class=&quot;s&quot;&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;traiter&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;span class=&quot;r&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;cl&quot;&gt;Unit&lt;/span&gt; &amp;lt; &lt;span class=&quot;co&quot;&gt;Traiter&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;tt&gt;
&lt;/tt&gt;  traits &lt;span class=&quot;sy&quot;&gt;:attack&lt;/span&gt;, &lt;span class=&quot;sy&quot;&gt;:defence&lt;/span&gt;, &lt;span class=&quot;sy&quot;&gt;:movement&lt;/span&gt;, &lt;span class=&quot;sy&quot;&gt;:zone_of_control&lt;/span&gt;, &lt;span class=&quot;sy&quot;&gt;:vision&lt;/span&gt;, &lt;span class=&quot;sy&quot;&gt;:strength&lt;/span&gt;,&lt;tt&gt;
&lt;/tt&gt;    &lt;span class=&quot;sy&quot;&gt;:location&lt;/span&gt;, &lt;span class=&quot;sy&quot;&gt;:cost&lt;/span&gt;, &lt;span class=&quot;sy&quot;&gt;:range&lt;/span&gt;, &lt;span class=&quot;sy&quot;&gt;:x&lt;/span&gt;, &lt;span class=&quot;sy&quot;&gt;:y&lt;/span&gt;, &lt;span class=&quot;sy&quot;&gt;:symbol&lt;/span&gt;, &lt;span class=&quot;sy&quot;&gt;:size&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;tt&gt;
&lt;/tt&gt;  &lt;span class=&quot;r&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;fu&quot;&gt;see?&lt;/span&gt;(x,y)&lt;tt&gt;
&lt;/tt&gt;    distance = &lt;span class=&quot;co&quot;&gt;Map&lt;/span&gt;.distance(&lt;span class=&quot;iv&quot;&gt;@location&lt;/span&gt;, [x,y])&lt;tt&gt;
&lt;/tt&gt;    &lt;span class=&quot;r&quot;&gt;return&lt;/span&gt; (distance &amp;lt;= &lt;span class=&quot;iv&quot;&gt;@vision&lt;/span&gt;)&lt;tt&gt;
&lt;/tt&gt;  &lt;span class=&quot;r&quot;&gt;end&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;tt&gt;
&lt;/tt&gt;  &lt;span class=&quot;r&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;fu&quot;&gt;move&lt;/span&gt;(x,y)&lt;tt&gt;
&lt;/tt&gt;    distance = &lt;span class=&quot;co&quot;&gt;Map&lt;/span&gt;.distance(&lt;span class=&quot;iv&quot;&gt;@location&lt;/span&gt;, [x,y])&lt;tt&gt;
&lt;/tt&gt;    &lt;span class=&quot;iv&quot;&gt;@location&lt;/span&gt; = [x, y] &lt;span class=&quot;r&quot;&gt;if&lt;/span&gt; (distance &amp;lt;= &lt;span class=&quot;iv&quot;&gt;@location&lt;/span&gt;)&lt;tt&gt;
&lt;/tt&gt;    &lt;span class=&quot;r&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;iv&quot;&gt;@location&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;  &lt;span class=&quot;r&quot;&gt;end&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;span class=&quot;r&quot;&gt;end&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;/tr&gt;&lt;/table&gt;

&lt;p&gt;From here, the yaml code to define my units has two parts:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Templates for the various unit types; to keep it dry.&lt;/li&gt;
&lt;li&gt;Class definitions&lt;/li&gt;
&lt;/ol&gt;
&lt;table class=&quot;CodeRay&quot;&gt;&lt;tr&gt;
  &lt;td title=&quot;click to toggle&quot; class=&quot;line_numbers&quot;&gt;&lt;pre&gt;1&lt;tt&gt;
&lt;/tt&gt;2&lt;tt&gt;
&lt;/tt&gt;3&lt;tt&gt;
&lt;/tt&gt;4&lt;tt&gt;
&lt;/tt&gt;&lt;strong&gt;5&lt;/strong&gt;&lt;tt&gt;
&lt;/tt&gt;6&lt;tt&gt;
&lt;/tt&gt;7&lt;tt&gt;
&lt;/tt&gt;8&lt;tt&gt;
&lt;/tt&gt;9&lt;tt&gt;
&lt;/tt&gt;&lt;strong&gt;10&lt;/strong&gt;&lt;tt&gt;
&lt;/tt&gt;11&lt;tt&gt;
&lt;/tt&gt;12&lt;tt&gt;
&lt;/tt&gt;13&lt;tt&gt;
&lt;/tt&gt;14&lt;tt&gt;
&lt;/tt&gt;&lt;strong&gt;15&lt;/strong&gt;&lt;tt&gt;
&lt;/tt&gt;16&lt;tt&gt;
&lt;/tt&gt;17&lt;tt&gt;
&lt;/tt&gt;18&lt;tt&gt;
&lt;/tt&gt;19&lt;tt&gt;
&lt;/tt&gt;&lt;strong&gt;20&lt;/strong&gt;&lt;tt&gt;
&lt;/tt&gt;21&lt;tt&gt;
&lt;/tt&gt;22&lt;tt&gt;
&lt;/tt&gt;23&lt;tt&gt;
&lt;/tt&gt;24&lt;tt&gt;
&lt;/tt&gt;&lt;strong&gt;25&lt;/strong&gt;&lt;tt&gt;
&lt;/tt&gt;26&lt;tt&gt;
&lt;/tt&gt;27&lt;tt&gt;
&lt;/tt&gt;28&lt;tt&gt;
&lt;/tt&gt;29&lt;tt&gt;
&lt;/tt&gt;&lt;strong&gt;30&lt;/strong&gt;&lt;tt&gt;
&lt;/tt&gt;31&lt;tt&gt;
&lt;/tt&gt;32&lt;tt&gt;
&lt;/tt&gt;33&lt;tt&gt;
&lt;/tt&gt;34&lt;tt&gt;
&lt;/tt&gt;&lt;strong&gt;35&lt;/strong&gt;&lt;tt&gt;
&lt;/tt&gt;36&lt;tt&gt;
&lt;/tt&gt;37&lt;tt&gt;
&lt;/tt&gt;38&lt;tt&gt;
&lt;/tt&gt;&lt;/pre&gt;&lt;/td&gt;
  &lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;tt&gt;
&lt;/tt&gt;---&lt;tt&gt;
&lt;/tt&gt;templates:&lt;tt&gt;
&lt;/tt&gt;  soldier:&lt;tt&gt;
&lt;/tt&gt;    movement: 1&lt;tt&gt;
&lt;/tt&gt;    vision: 1&lt;tt&gt;
&lt;/tt&gt;    zone_of_control: 1&lt;tt&gt;
&lt;/tt&gt;    range: 1&lt;tt&gt;
&lt;/tt&gt;  scout:&lt;tt&gt;
&lt;/tt&gt;    movement: 3&lt;tt&gt;
&lt;/tt&gt;    vision: 2&lt;tt&gt;
&lt;/tt&gt;    zone_of_control: 1&lt;tt&gt;
&lt;/tt&gt;    range: 1&lt;tt&gt;
&lt;/tt&gt;classes:&lt;tt&gt;
&lt;/tt&gt;- name: militia&lt;tt&gt;
&lt;/tt&gt;  template: soldier&lt;tt&gt;
&lt;/tt&gt;  attributes:&lt;tt&gt;
&lt;/tt&gt;    strength: 50&lt;tt&gt;
&lt;/tt&gt;    attack: -10&lt;tt&gt;
&lt;/tt&gt;    defence: 10&lt;tt&gt;
&lt;/tt&gt;    cost: 50&lt;tt&gt;
&lt;/tt&gt;    symbol: m&lt;tt&gt;
&lt;/tt&gt;- name: rifleman&lt;tt&gt;
&lt;/tt&gt;  template: soldier&lt;tt&gt;
&lt;/tt&gt;  attributes:&lt;tt&gt;
&lt;/tt&gt;    strength: 100&lt;tt&gt;
&lt;/tt&gt;    attack: 30&lt;tt&gt;
&lt;/tt&gt;    defence: 30&lt;tt&gt;
&lt;/tt&gt;    cost: 125&lt;tt&gt;
&lt;/tt&gt;    symbol: r&lt;tt&gt;
&lt;/tt&gt;- name: scout&lt;tt&gt;
&lt;/tt&gt;  template: scout&lt;tt&gt;
&lt;/tt&gt;  attributes:&lt;tt&gt;
&lt;/tt&gt;    strength: 20&lt;tt&gt;
&lt;/tt&gt;    attack: 10&lt;tt&gt;
&lt;/tt&gt;    defence: 10&lt;tt&gt;
&lt;/tt&gt;    cost: 200&lt;tt&gt;
&lt;/tt&gt;    symbol: s&lt;tt&gt;
&lt;/tt&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;/tr&gt;&lt;/table&gt;

&lt;p&gt;In each of the classes, I am declaring an (optional) template, as well as (optional) attributes.  The code which performs the loading of the yaml and the creation of the classes follows:&lt;/p&gt;
&lt;table class=&quot;CodeRay&quot;&gt;&lt;tr&gt;
  &lt;td title=&quot;click to toggle&quot; class=&quot;line_numbers&quot;&gt;&lt;pre&gt;1&lt;tt&gt;
&lt;/tt&gt;2&lt;tt&gt;
&lt;/tt&gt;3&lt;tt&gt;
&lt;/tt&gt;4&lt;tt&gt;
&lt;/tt&gt;&lt;strong&gt;5&lt;/strong&gt;&lt;tt&gt;
&lt;/tt&gt;6&lt;tt&gt;
&lt;/tt&gt;7&lt;tt&gt;
&lt;/tt&gt;8&lt;tt&gt;
&lt;/tt&gt;9&lt;tt&gt;
&lt;/tt&gt;&lt;strong&gt;10&lt;/strong&gt;&lt;tt&gt;
&lt;/tt&gt;11&lt;tt&gt;
&lt;/tt&gt;12&lt;tt&gt;
&lt;/tt&gt;13&lt;tt&gt;
&lt;/tt&gt;14&lt;tt&gt;
&lt;/tt&gt;&lt;strong&gt;15&lt;/strong&gt;&lt;tt&gt;
&lt;/tt&gt;16&lt;tt&gt;
&lt;/tt&gt;17&lt;tt&gt;
&lt;/tt&gt;18&lt;tt&gt;
&lt;/tt&gt;19&lt;tt&gt;
&lt;/tt&gt;&lt;strong&gt;20&lt;/strong&gt;&lt;tt&gt;
&lt;/tt&gt;21&lt;tt&gt;
&lt;/tt&gt;22&lt;tt&gt;
&lt;/tt&gt;23&lt;tt&gt;
&lt;/tt&gt;&lt;/pre&gt;&lt;/td&gt;
  &lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;tt&gt;
&lt;/tt&gt;require &lt;span class=&quot;s&quot;&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;yaml&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;span class=&quot;r&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;cl&quot;&gt;Loader&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;  &lt;span class=&quot;r&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;pc&quot;&gt;self&lt;/span&gt;.load_classes(file, parent = &lt;span class=&quot;pc&quot;&gt;nil&lt;/span&gt;)&lt;tt&gt;
&lt;/tt&gt;    &lt;span class=&quot;r&quot;&gt;begin&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;      y = &lt;span class=&quot;co&quot;&gt;YAML&lt;/span&gt;.load(&lt;span class=&quot;co&quot;&gt;File&lt;/span&gt;.open(file))&lt;tt&gt;
&lt;/tt&gt;      templates = y[&lt;span class=&quot;s&quot;&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;templates&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;]&lt;tt&gt;
&lt;/tt&gt;      klasses = y[&lt;span class=&quot;s&quot;&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;classes&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;]&lt;tt&gt;
&lt;/tt&gt;      klasses.each &lt;span class=&quot;r&quot;&gt;do&lt;/span&gt; |klass|&lt;tt&gt;
&lt;/tt&gt;        puts klass[&lt;span class=&quot;s&quot;&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;/span&gt;]&lt;tt&gt;
&lt;/tt&gt;        k = &lt;span class=&quot;co&quot;&gt;Object&lt;/span&gt;.const_set(klass[&lt;span class=&quot;s&quot;&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;/span&gt;].capitalize,&lt;tt&gt;
&lt;/tt&gt;                             &lt;span class=&quot;co&quot;&gt;Class&lt;/span&gt;.new(parent || &lt;span class=&quot;co&quot;&gt;Object&lt;/span&gt;.const_get(klass[&lt;span class=&quot;s&quot;&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;parent&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;/span&gt;].capitalize)))&lt;tt&gt;
&lt;/tt&gt;        k.class_eval  &lt;span class=&quot;s&quot;&gt;&lt;span class=&quot;dl&quot;&gt;&amp;lt;&amp;lt;EOF&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&lt;span class=&quot;k&quot;&gt;&lt;tt&gt;
&lt;/tt&gt;  &lt;/span&gt;&lt;span class=&quot;il&quot;&gt;&lt;span class=&quot;dl&quot;&gt;#{&lt;/span&gt;(klass[&lt;span class=&quot;s&quot;&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;traits&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;/span&gt;].nil? ? &lt;span class=&quot;s&quot;&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt; : &lt;span class=&quot;s&quot;&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;traits &lt;/span&gt;&lt;span class=&quot;il&quot;&gt;&lt;span class=&quot;dl&quot;&gt;#{&lt;/span&gt;klass[&lt;span class=&quot;s&quot;&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;traits&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;/span&gt;].map{ |trait| &lt;span class=&quot;s&quot;&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;il&quot;&gt;&lt;span class=&quot;dl&quot;&gt;#{&lt;/span&gt;trait&lt;span class=&quot;dl&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;}.join(&lt;span class=&quot;s&quot;&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;)&lt;span class=&quot;dl&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;)&lt;span class=&quot;dl&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;&lt;tt&gt;
&lt;/tt&gt;  &lt;/span&gt;&lt;span class=&quot;il&quot;&gt;&lt;span class=&quot;dl&quot;&gt;#{&lt;/span&gt;(templates[&lt;span class=&quot;s&quot;&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;il&quot;&gt;&lt;span class=&quot;dl&quot;&gt;#{&lt;/span&gt;klass[&lt;span class=&quot;s&quot;&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;template&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;/span&gt;]&lt;span class=&quot;dl&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;] || {}).merge((klass[&lt;span class=&quot;s&quot;&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;attributes&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;/span&gt;] || {})).sort.map{|t| t[&lt;span class=&quot;i&quot;&gt;1&lt;/span&gt;]=&lt;span class=&quot;s&quot;&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;il&quot;&gt;&lt;span class=&quot;dl&quot;&gt;#{&lt;/span&gt;t[&lt;span class=&quot;i&quot;&gt;1&lt;/span&gt;]&lt;span class=&quot;dl&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;r&quot;&gt;if&lt;/span&gt; t[&lt;span class=&quot;i&quot;&gt;1&lt;/span&gt;].instance_of?(&lt;span class=&quot;co&quot;&gt;String&lt;/span&gt;); t.join(&lt;span class=&quot;s&quot;&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt; &lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;).downcase}.join(&lt;span class=&quot;s&quot;&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;ch&quot;&gt;\n&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;)&lt;span class=&quot;dl&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&lt;tt&gt;
&lt;/tt&gt;EOF&lt;/span&gt;&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;      &lt;span class=&quot;r&quot;&gt;end&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;    &lt;span class=&quot;r&quot;&gt;rescue&lt;/span&gt; &lt;span class=&quot;co&quot;&gt;Exception&lt;/span&gt; =&amp;gt; e&lt;tt&gt;
&lt;/tt&gt;      puts &lt;span class=&quot;s&quot;&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;Error parsing File &lt;/span&gt;&lt;span class=&quot;il&quot;&gt;&lt;span class=&quot;dl&quot;&gt;#{&lt;/span&gt;file&lt;span class=&quot;dl&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;: &lt;/span&gt;&lt;span class=&quot;il&quot;&gt;&lt;span class=&quot;dl&quot;&gt;#{&lt;/span&gt;e&lt;span class=&quot;dl&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;    &lt;span class=&quot;r&quot;&gt;end&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;  &lt;span class=&quot;r&quot;&gt;end&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;span class=&quot;r&quot;&gt;end&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;/tr&gt;&lt;/table&gt;

&lt;p&gt;The method is a class method, so it's invoked as &lt;code&gt;Loader.load_classes(file, Unit)&lt;/code&gt;; if I choose not to pass in the second argument, then I need to specify classes in my yaml file for each class.  I then load the yaml and for clarity split it into templates and classes.  Then for each class, I do the following:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Output the class name; this could be suppressed if desired&lt;/li&gt;
&lt;li&gt;Create a &lt;code&gt;Class&lt;/code&gt; instance either using the parent argument or doing a lookup to find the parent and register it with &lt;code&gt;Object&lt;/code&gt;.
&lt;li&gt;Taking the class instance, I then add to it with &lt;code&gt;class_eval&lt;/code&gt; and add the following:
&lt;ol&gt;
&lt;li&gt;Any additional traits which might be defined for the class&lt;/li&gt;
&lt;li&gt;Merging the (optional) template's traits and  the class' (optional) traits, I tranform them as follows:
&lt;ul&gt;
&lt;li&gt;Numerics are changed to &quot;trait amount&quot;, as in &quot;strength 10&quot;&lt;/li&gt;
&lt;li&gt;Strings are escaped to look like &quot;symbol 's'&quot;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;There's definite places for expansion/improvement -- I could modify it so that a trait could be an array or a hash.  also I could add the ability to embed code in the yaml file.  But, all in all, it does save typing and makes my definition of units and terrains more flexible.&lt;/p&gt;
&lt;p&gt;I'll gladly listen to any suggestions for improvement&lt;/p&gt;
          </content>  </entry>
  <entry xml:base="http://aetherical.com/">
    <author>
      <name>Matt Williams</name>
    </author>
    <id>tag:aetherical.com,2008-04-18:58</id>
    <published>2008-04-18T15:32:00Z</published>
    <updated>2008-04-18T16:13:51Z</updated>
    <category term="blog"/>
    <category term="syndicated"/>
    <category term="metaprogramming"/>
    <category term="ruby"/>
    <category term="ruby2ruby"/>
    <link href="http://aetherical.com/2008/4/18/watching-changes" rel="alternate" type="text/html"/>
    <title>Watching changes</title>
<summary type="html">The ruby2ruby gem allows you to peer into a class's methods and watch changes due to metaprogramming.</summary><content type="html">
            The ruby2ruby gem allows you to peer into a class's methods and watch changes due to metaprogramming.
&lt;p&gt;ruby2ruby is a gem created by the &lt;a href=&quot;http://www.zenspider.com/Languages/Ruby/Seattle/index.html&quot;&gt;Seattle Ruby Brigade&lt;/a&gt;.  You can install it, like any other gem, with &lt;code&gt;gem install ruby2ruby&lt;/code&gt;.  Once installed, it lets you peer inside a Class' methods.&lt;/p&gt;
&lt;table class=&quot;CodeRay&quot;&gt;&lt;tr&gt;
  &lt;td title=&quot;click to toggle&quot; class=&quot;line_numbers&quot;&gt;&lt;pre&gt;1&lt;tt&gt;
&lt;/tt&gt;2&lt;tt&gt;
&lt;/tt&gt;3&lt;tt&gt;
&lt;/tt&gt;4&lt;tt&gt;
&lt;/tt&gt;&lt;strong&gt;5&lt;/strong&gt;&lt;tt&gt;
&lt;/tt&gt;6&lt;tt&gt;
&lt;/tt&gt;7&lt;tt&gt;
&lt;/tt&gt;8&lt;tt&gt;
&lt;/tt&gt;9&lt;tt&gt;
&lt;/tt&gt;&lt;strong&gt;10&lt;/strong&gt;&lt;tt&gt;
&lt;/tt&gt;11&lt;tt&gt;
&lt;/tt&gt;12&lt;tt&gt;
&lt;/tt&gt;13&lt;tt&gt;
&lt;/tt&gt;14&lt;tt&gt;
&lt;/tt&gt;&lt;strong&gt;15&lt;/strong&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;/pre&gt;&lt;/td&gt;
  &lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;span class=&quot;er&quot;&gt;$&lt;/span&gt; irb&lt;tt&gt;
&lt;/tt&gt;irb(main):&lt;span class=&quot;i&quot;&gt;001&lt;/span&gt;:&lt;span class=&quot;i&quot;&gt;0&lt;/span&gt;&amp;gt; require &lt;span class=&quot;s&quot;&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;rubygems&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;=&amp;gt; &lt;span class=&quot;pc&quot;&gt;true&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;irb(main):&lt;span class=&quot;i&quot;&gt;002&lt;/span&gt;:&lt;span class=&quot;i&quot;&gt;0&lt;/span&gt;&amp;gt; require &lt;span class=&quot;s&quot;&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;ruby2ruby&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;=&amp;gt; &lt;span class=&quot;pc&quot;&gt;true&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;irb(main):&lt;span class=&quot;i&quot;&gt;003&lt;/span&gt;:&lt;span class=&quot;i&quot;&gt;0&lt;/span&gt;&amp;gt; &lt;span class=&quot;r&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;cl&quot;&gt;Foo&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;irb(main):&lt;span class=&quot;i&quot;&gt;004&lt;/span&gt;:&lt;span class=&quot;i&quot;&gt;1&lt;/span&gt;&amp;gt; attr_accessor &lt;span class=&quot;sy&quot;&gt;:fud&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;irb(main):&lt;span class=&quot;i&quot;&gt;005&lt;/span&gt;:&lt;span class=&quot;i&quot;&gt;1&lt;/span&gt;&amp;gt; &lt;span class=&quot;r&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;fu&quot;&gt;initialize&lt;/span&gt;(fud)&lt;tt&gt;
&lt;/tt&gt;irb(main):&lt;span class=&quot;i&quot;&gt;006&lt;/span&gt;:&lt;span class=&quot;i&quot;&gt;2&lt;/span&gt;&amp;gt; &lt;span class=&quot;iv&quot;&gt;@fud&lt;/span&gt; = fud&lt;tt&gt;
&lt;/tt&gt;irb(main):&lt;span class=&quot;i&quot;&gt;007&lt;/span&gt;:&lt;span class=&quot;i&quot;&gt;2&lt;/span&gt;&amp;gt; &lt;span class=&quot;r&quot;&gt;end&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;irb(main):&lt;span class=&quot;i&quot;&gt;00&lt;/span&gt;&lt;span class=&quot;i&quot;&gt;8&lt;/span&gt;:&lt;span class=&quot;i&quot;&gt;1&lt;/span&gt;&amp;gt; &lt;span class=&quot;r&quot;&gt;end&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;=&amp;gt; &lt;span class=&quot;pc&quot;&gt;nil&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;irb(main):&lt;span class=&quot;i&quot;&gt;00&lt;/span&gt;&lt;span class=&quot;i&quot;&gt;9&lt;/span&gt;:&lt;span class=&quot;i&quot;&gt;0&lt;/span&gt;&amp;gt; &lt;span class=&quot;co&quot;&gt;Ruby2Ruby&lt;/span&gt;.translate &lt;span class=&quot;co&quot;&gt;Foo&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;=&amp;gt; &lt;span class=&quot;s&quot;&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;class Foo &amp;lt; Object&lt;/span&gt;&lt;span class=&quot;ch&quot;&gt;\n&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;  attr_reader :fud&lt;/span&gt;&lt;span class=&quot;ch&quot;&gt;\n&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;  &lt;/span&gt;&lt;span class=&quot;ch&quot;&gt;\n&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;  attr_writer :fud&lt;/span&gt;&lt;span class=&quot;ch&quot;&gt;\n&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;  &lt;/span&gt;&lt;span class=&quot;ch&quot;&gt;\n&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;  def initialize(fud)&lt;/span&gt;&lt;span class=&quot;ch&quot;&gt;\n&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;    @fud = fud&lt;/span&gt;&lt;span class=&quot;ch&quot;&gt;\n&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;  end&lt;/span&gt;&lt;span class=&quot;ch&quot;&gt;\n&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;/tr&gt;&lt;/table&gt;

&lt;p&gt;Here I've created a simple class.  One thing that is interesting, the interpreter expands &lt;code&gt;attr_accessor&lt;/code&gt; into both &lt;code&gt;attr_reader&lt;/code&gt; and &lt;code&gt;attr_writer&lt;/code&gt; for me automatically.  One of the requirements of &lt;code&gt;Ruby2Ruby&lt;/code&gt; is that it works on Classes, not on instances:&lt;/p&gt;
&lt;table class=&quot;CodeRay&quot;&gt;&lt;tr&gt;
  &lt;td title=&quot;click to toggle&quot; class=&quot;line_numbers&quot;&gt;&lt;pre&gt;1&lt;tt&gt;
&lt;/tt&gt;2&lt;tt&gt;
&lt;/tt&gt;3&lt;tt&gt;
&lt;/tt&gt;4&lt;tt&gt;
&lt;/tt&gt;&lt;strong&gt;5&lt;/strong&gt;&lt;tt&gt;
&lt;/tt&gt;6&lt;tt&gt;
&lt;/tt&gt;7&lt;tt&gt;
&lt;/tt&gt;8&lt;tt&gt;
&lt;/tt&gt;9&lt;tt&gt;
&lt;/tt&gt;&lt;strong&gt;10&lt;/strong&gt;&lt;tt&gt;
&lt;/tt&gt;11&lt;tt&gt;
&lt;/tt&gt;12&lt;tt&gt;
&lt;/tt&gt;&lt;/pre&gt;&lt;/td&gt;
  &lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;tt&gt;
&lt;/tt&gt;irb(main):&lt;span class=&quot;i&quot;&gt;010&lt;/span&gt;:&lt;span class=&quot;i&quot;&gt;0&lt;/span&gt;&amp;gt; f=&lt;span class=&quot;co&quot;&gt;Foo&lt;/span&gt;.new(&lt;span class=&quot;i&quot;&gt;5&lt;/span&gt;)&lt;tt&gt;
&lt;/tt&gt;=&amp;gt; &lt;span class=&quot;c&quot;&gt;#&amp;lt;Foo:0x2b82e560d608 @fud=5&amp;gt;&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;irb(main):&lt;span class=&quot;i&quot;&gt;011&lt;/span&gt;:&lt;span class=&quot;i&quot;&gt;0&lt;/span&gt;&amp;gt; &lt;span class=&quot;co&quot;&gt;Ruby2Ruby&lt;/span&gt;.translate f&lt;tt&gt;
&lt;/tt&gt;&lt;span class=&quot;co&quot;&gt;NoMethodError&lt;/span&gt;: undefined method &lt;span class=&quot;sh&quot;&gt;&lt;span class=&quot;dl&quot;&gt;`&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;instance_methods' for #&amp;lt;Foo:0x2b82e560d608 @fud=5&amp;gt;&lt;tt&gt;
&lt;/tt&gt;        from /usr/lib/ruby/gems/1.8/gems/ParseTree-2.1.1/lib/parse_tree.rb:115:in &lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;`&lt;/span&gt;&lt;/span&gt;parse_tree&lt;span class=&quot;s&quot;&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;&lt;tt&gt;
&lt;/tt&gt;        from /usr/lib/ruby/gems/1.8/gems/ParseTree-2.1.1/lib/parse_tree.rb:99:in `parse_tree&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;        from &lt;span class=&quot;rx&quot;&gt;&lt;span class=&quot;dl&quot;&gt;/&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;usr&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;/&lt;/span&gt;&lt;/span&gt;lib/ruby/gems/&lt;span class=&quot;fl&quot;&gt;1.8&lt;/span&gt;/gems/&lt;span class=&quot;co&quot;&gt;ParseTree&lt;/span&gt;&lt;span class=&quot;fl&quot;&gt;-2.1&lt;/span&gt;.&lt;span class=&quot;i&quot;&gt;1&lt;/span&gt;/lib/parse_tree.rb:&lt;span class=&quot;i&quot;&gt;71&lt;/span&gt;&lt;span class=&quot;sy&quot;&gt;:in&lt;/span&gt; &lt;span class=&quot;sh&quot;&gt;&lt;span class=&quot;dl&quot;&gt;`&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;translate'&lt;tt&gt;
&lt;/tt&gt;        from /usr/lib/ruby/gems/1.8/gems/ruby2ruby-1.1.8/lib/ruby2ruby.rb:31:in &lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;`&lt;/span&gt;&lt;/span&gt;translate&lt;span class=&quot;s&quot;&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;&lt;tt&gt;
&lt;/tt&gt;        from (irb):11&lt;tt&gt;
&lt;/tt&gt;irb(main):012:0&amp;gt; Ruby2Ruby.translate f.class&lt;tt&gt;
&lt;/tt&gt;=&amp;gt; &amp;quot;class Foo &amp;lt; Object&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;\n&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;  attr_reader :fud&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;\n&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;  &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;\n&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;  attr_writer :fud&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;\n&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;  &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;\n&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;  def initialize(fud)&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;\n&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;    @fud = fud&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;\n&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;  end&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;\n&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;end&amp;quot;&lt;tt&gt;
&lt;/tt&gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;/tr&gt;&lt;/table&gt;

&lt;p&gt;We can compare the code as it changes, too:&lt;/p&gt;
&lt;table class=&quot;CodeRay&quot;&gt;&lt;tr&gt;
  &lt;td title=&quot;click to toggle&quot; class=&quot;line_numbers&quot;&gt;&lt;pre&gt;1&lt;tt&gt;
&lt;/tt&gt;2&lt;tt&gt;
&lt;/tt&gt;3&lt;tt&gt;
&lt;/tt&gt;4&lt;tt&gt;
&lt;/tt&gt;&lt;strong&gt;5&lt;/strong&gt;&lt;tt&gt;
&lt;/tt&gt;6&lt;tt&gt;
&lt;/tt&gt;7&lt;tt&gt;
&lt;/tt&gt;8&lt;tt&gt;
&lt;/tt&gt;9&lt;tt&gt;
&lt;/tt&gt;&lt;/pre&gt;&lt;/td&gt;
  &lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;tt&gt;
&lt;/tt&gt;irb(main):&lt;span class=&quot;i&quot;&gt;013&lt;/span&gt;:&lt;span class=&quot;i&quot;&gt;0&lt;/span&gt;&amp;gt; &lt;span class=&quot;r&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;cl&quot;&gt;Foo&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;irb(main):&lt;span class=&quot;i&quot;&gt;014&lt;/span&gt;:&lt;span class=&quot;i&quot;&gt;1&lt;/span&gt;&amp;gt; &lt;span class=&quot;r&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;fu&quot;&gt;something&lt;/span&gt;(bar)&lt;tt&gt;
&lt;/tt&gt;irb(main):&lt;span class=&quot;i&quot;&gt;015&lt;/span&gt;:&lt;span class=&quot;i&quot;&gt;2&lt;/span&gt;&amp;gt; puts bar&lt;tt&gt;
&lt;/tt&gt;irb(main):&lt;span class=&quot;i&quot;&gt;016&lt;/span&gt;:&lt;span class=&quot;i&quot;&gt;2&lt;/span&gt;&amp;gt; &lt;span class=&quot;r&quot;&gt;end&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;irb(main):&lt;span class=&quot;i&quot;&gt;017&lt;/span&gt;:&lt;span class=&quot;i&quot;&gt;1&lt;/span&gt;&amp;gt; &lt;span class=&quot;r&quot;&gt;end&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;=&amp;gt; &lt;span class=&quot;pc&quot;&gt;nil&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;irb(main):&lt;span class=&quot;i&quot;&gt;01&lt;/span&gt;&lt;span class=&quot;i&quot;&gt;8&lt;/span&gt;:&lt;span class=&quot;i&quot;&gt;0&lt;/span&gt;&amp;gt; &lt;span class=&quot;co&quot;&gt;Ruby2Ruby&lt;/span&gt;.translate &lt;span class=&quot;co&quot;&gt;Foo&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;=&amp;gt; &lt;span class=&quot;s&quot;&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;class Foo &amp;lt; Object&lt;/span&gt;&lt;span class=&quot;ch&quot;&gt;\n&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;  attr_reader :fud&lt;/span&gt;&lt;span class=&quot;ch&quot;&gt;\n&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;  &lt;/span&gt;&lt;span class=&quot;ch&quot;&gt;\n&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;  attr_writer :fud&lt;/span&gt;&lt;span class=&quot;ch&quot;&gt;\n&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;  &lt;/span&gt;&lt;span class=&quot;ch&quot;&gt;\n&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;  def initialize(fud)&lt;/span&gt;&lt;span class=&quot;ch&quot;&gt;\n&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;    @fud = fud&lt;/span&gt;&lt;span class=&quot;ch&quot;&gt;\n&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;  end&lt;/span&gt;&lt;span class=&quot;ch&quot;&gt;\n&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;  &lt;/span&gt;&lt;span class=&quot;ch&quot;&gt;\n&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;  def something(bar)&lt;/span&gt;&lt;span class=&quot;ch&quot;&gt;\n&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;    puts(bar)&lt;/span&gt;&lt;span class=&quot;ch&quot;&gt;\n&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;  end&lt;/span&gt;&lt;span class=&quot;ch&quot;&gt;\n&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;/tr&gt;&lt;/table&gt;

&lt;p&gt;There's a lot more which can be done here, and it will be the subject of a further entry.&lt;/p&gt;
          </content>  </entry>
  <entry xml:base="http://aetherical.com/">
    <author>
      <name>Matt Williams</name>
    </author>
    <id>tag:aetherical.com,2008-04-09:54</id>
    <published>2008-04-09T13:13:00Z</published>
    <updated>2008-04-09T13:14:26Z</updated>
    <category term="blog"/>
    <category term="syndicated"/>
    <category term="programming"/>
    <category term="ruby"/>
    <link href="http://aetherical.com/2008/4/9/define-rubyfied" rel="alternate" type="text/html"/>
    <title>#define rubyfied</title>
<content type="html">
            &lt;p&gt;Remember &lt;code&gt;#defined FOO = 1;&lt;/code&gt; from your C days?  Or &lt;code&gt;public static int FOO = 1;&lt;/code&gt; from java?  Well, I recently had reason to use this functionality within Ruby when I wanted to define a series of types which would each have a unique id used in a database, but I really didn't want to waste the space on a string.
&lt;/p&gt;
&lt;p&gt;I ended up with two methods, the first which takes a name and an enumerable, sets class variables for each element of an array (such as &lt;code&gt;%w(The fat cat sat on a hat)&lt;/code&gt;) as well as a method for resolving an integer to a string.&lt;p&gt;
&lt;p&gt;Taking the following class:&lt;/p&gt;
&lt;table class=&quot;CodeRay&quot;&gt;&lt;tr&gt;
  &lt;td title=&quot;click to toggle&quot; class=&quot;line_numbers&quot;&gt;&lt;pre&gt;1&lt;tt&gt;
&lt;/tt&gt;2&lt;tt&gt;
&lt;/tt&gt;3&lt;tt&gt;
&lt;/tt&gt;4&lt;tt&gt;
&lt;/tt&gt;&lt;strong&gt;5&lt;/strong&gt;&lt;tt&gt;
&lt;/tt&gt;6&lt;tt&gt;
&lt;/tt&gt;&lt;/pre&gt;&lt;/td&gt;
  &lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;tt&gt;
&lt;/tt&gt;require &lt;span class=&quot;s&quot;&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;definer&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;span class=&quot;r&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;cl&quot;&gt;Project&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;  define_class_types &lt;span class=&quot;sy&quot;&gt;:states&lt;/span&gt;, &lt;span class=&quot;s&quot;&gt;&lt;span class=&quot;dl&quot;&gt;%w(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;planning development testing production&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;)&lt;/span&gt;&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;  define &lt;span class=&quot;sy&quot;&gt;:myself&lt;/span&gt;, &lt;span class=&quot;i&quot;&gt;1&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;span class=&quot;r&quot;&gt;end&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;/tr&gt;&lt;/table&gt;

&lt;p&gt;you would have the following definitions:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;Project.planning&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;Project.development&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;Project.testing&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;Project.prodution&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;Project.@@states&lt;/code&gt;(not accessible outside of class, but that's easily remedied)&lt;/li&gt;
&lt;li&gt;&lt;code&gt;Project.myself&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Additionally, you would have a method &lt;code&gt;Project.state_name(state)&lt;/code&gt; which would take a integer and return the string associated with that state.  So, &lt;code&gt;Project.state_name(0)&lt;/code&gt; or &lt;code&gt;Project.state_name(Project.planning)&lt;/code&gt; would both return &quot;planning&quot;.&lt;/p&gt;
&lt;p&gt;In the &lt;code&gt;define_class_types&lt;/code&gt; method, the name can be either pluralized or singular.  The array of the types will be pluralized (as in states above) and the method for getting the string singularized (as in &lt;code&gt;Project.state_name&lt;/code&gt; above.&lt;/p&gt;
&lt;p&gt;There is one dependency -- it uses &lt;a href=&quot;http://as.rubyonrails.com/&quot;&gt;ActiveSupport&lt;/a&gt;'s &lt;code&gt;pluralize&lt;/code&gt; and &lt;code&gt;singularize&lt;/code&gt;.  The code follows below or you can download it here: &lt;a href=&quot;http://www.aetherical.com/assets/2008/4/7/definer.rb&quot;&gt;definer.rb&lt;/a&gt;&lt;/p&gt;
&lt;table class=&quot;CodeRay&quot;&gt;&lt;tr&gt;
  &lt;td title=&quot;click to toggle&quot; class=&quot;line_numbers&quot;&gt;&lt;pre&gt;1&lt;tt&gt;
&lt;/tt&gt;2&lt;tt&gt;
&lt;/tt&gt;3&lt;tt&gt;
&lt;/tt&gt;4&lt;tt&gt;
&lt;/tt&gt;&lt;strong&gt;5&lt;/strong&gt;&lt;tt&gt;
&lt;/tt&gt;6&lt;tt&gt;
&lt;/tt&gt;7&lt;tt&gt;
&lt;/tt&gt;8&lt;tt&gt;
&lt;/tt&gt;9&lt;tt&gt;
&lt;/tt&gt;&lt;strong&gt;10&lt;/strong&gt;&lt;tt&gt;
&lt;/tt&gt;11&lt;tt&gt;
&lt;/tt&gt;12&lt;tt&gt;
&lt;/tt&gt;13&lt;tt&gt;
&lt;/tt&gt;14&lt;tt&gt;
&lt;/tt&gt;&lt;strong&gt;15&lt;/strong&gt;&lt;tt&gt;
&lt;/tt&gt;16&lt;tt&gt;
&lt;/tt&gt;17&lt;tt&gt;
&lt;/tt&gt;18&lt;tt&gt;
&lt;/tt&gt;19&lt;tt&gt;
&lt;/tt&gt;&lt;strong&gt;20&lt;/strong&gt;&lt;tt&gt;
&lt;/tt&gt;21&lt;tt&gt;
&lt;/tt&gt;22&lt;tt&gt;
&lt;/tt&gt;23&lt;tt&gt;
&lt;/tt&gt;24&lt;tt&gt;
&lt;/tt&gt;&lt;strong&gt;25&lt;/strong&gt;&lt;tt&gt;
&lt;/tt&gt;26&lt;tt&gt;
&lt;/tt&gt;27&lt;tt&gt;
&lt;/tt&gt;28&lt;tt&gt;
&lt;/tt&gt;29&lt;tt&gt;
&lt;/tt&gt;&lt;strong&gt;30&lt;/strong&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;/pre&gt;&lt;/td&gt;
  &lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;tt&gt;
&lt;/tt&gt;require &lt;span class=&quot;s&quot;&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;active_support&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;span class=&quot;r&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;cl&quot;&gt;Module&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;  &lt;span class=&quot;r&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;fu&quot;&gt;class_attr_reader&lt;/span&gt;(*symbols)&lt;tt&gt;
&lt;/tt&gt;    symbols.each &lt;span class=&quot;r&quot;&gt;do&lt;/span&gt; |symbol|&lt;tt&gt;
&lt;/tt&gt;      &lt;span class=&quot;pc&quot;&gt;self&lt;/span&gt;.class.send(&lt;span class=&quot;sy&quot;&gt;:define_method&lt;/span&gt;, symbol) &lt;span class=&quot;r&quot;&gt;do&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;        &lt;span class=&quot;pc&quot;&gt;self&lt;/span&gt;.class_eval &lt;span class=&quot;s&quot;&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;@@&lt;/span&gt;&lt;span class=&quot;il&quot;&gt;&lt;span class=&quot;dl&quot;&gt;#{&lt;/span&gt;symbol&lt;span class=&quot;dl&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;      &lt;span class=&quot;r&quot;&gt;end&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;    &lt;span class=&quot;r&quot;&gt;end&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;  &lt;span class=&quot;r&quot;&gt;end&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;tt&gt;
&lt;/tt&gt;  &lt;span class=&quot;r&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;fu&quot;&gt;define&lt;/span&gt;(name,value)&lt;tt&gt;
&lt;/tt&gt;    name = name.to_s&lt;tt&gt;
&lt;/tt&gt;    class_variable_set(&lt;span class=&quot;s&quot;&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;@@&lt;/span&gt;&lt;span class=&quot;il&quot;&gt;&lt;span class=&quot;dl&quot;&gt;#{&lt;/span&gt;name&lt;span class=&quot;dl&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;,value)&lt;tt&gt;
&lt;/tt&gt;    class_attr_reader(name)&lt;tt&gt;
&lt;/tt&gt;  &lt;span class=&quot;r&quot;&gt;end&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;tt&gt;
&lt;/tt&gt;  &lt;span class=&quot;r&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;fu&quot;&gt;add_class_types&lt;/span&gt;(name, types = [])&lt;tt&gt;
&lt;/tt&gt;    name = name.to_s&lt;tt&gt;
&lt;/tt&gt;    class_variable_set(&lt;span class=&quot;s&quot;&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;@@&lt;/span&gt;&lt;span class=&quot;il&quot;&gt;&lt;span class=&quot;dl&quot;&gt;#{&lt;/span&gt;name.pluralize&lt;span class=&quot;dl&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;,types)&lt;tt&gt;
&lt;/tt&gt;    types.each_with_index &lt;span class=&quot;r&quot;&gt;do&lt;/span&gt; |type, index|&lt;tt&gt;
&lt;/tt&gt;      class_variable_set(&lt;span class=&quot;s&quot;&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;@@&lt;/span&gt;&lt;span class=&quot;il&quot;&gt;&lt;span class=&quot;dl&quot;&gt;#{&lt;/span&gt;type&lt;span class=&quot;dl&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;, index)&lt;tt&gt;
&lt;/tt&gt;      class_attr_reader(type)&lt;tt&gt;
&lt;/tt&gt;    &lt;span class=&quot;r&quot;&gt;end&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;    &lt;span class=&quot;pc&quot;&gt;self&lt;/span&gt;.class.send(&lt;span class=&quot;sy&quot;&gt;:define_method&lt;/span&gt;,&lt;span class=&quot;s&quot;&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;il&quot;&gt;&lt;span class=&quot;dl&quot;&gt;#{&lt;/span&gt;name.singularize&lt;span class=&quot;dl&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;_name&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;) &lt;span class=&quot;r&quot;&gt;do&lt;/span&gt; |arg|&lt;tt&gt;
&lt;/tt&gt;      &lt;span class=&quot;pc&quot;&gt;self&lt;/span&gt;.class_eval &lt;span class=&quot;s&quot;&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;@@&lt;/span&gt;&lt;span class=&quot;il&quot;&gt;&lt;span class=&quot;dl&quot;&gt;#{&lt;/span&gt;name.pluralize&lt;span class=&quot;dl&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;il&quot;&gt;&lt;span class=&quot;dl&quot;&gt;#{&lt;/span&gt;arg&lt;span class=&quot;dl&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;    &lt;span class=&quot;r&quot;&gt;end&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;  &lt;span class=&quot;r&quot;&gt;end&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;span class=&quot;r&quot;&gt;end&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;/tr&gt;&lt;/table&gt;
          </content>  </entry>
  <entry xml:base="http://aetherical.com/">
    <author>
      <name>Matt Williams</name>
    </author>
    <id>tag:aetherical.com,2008-04-08:55</id>
    <published>2008-04-08T18:00:00Z</published>
    <updated>2008-04-08T19:26:05Z</updated>
    <category term="syndicated"/>
    <category term="Tips"/>
    <category term="programming"/>
    <category term="ruby"/>
    <link href="http://aetherical.com/2008/4/8/order-matters" rel="alternate" type="text/html"/>
    <title>Order Matters!</title>
<content type="html">
            The order in which operations occur can often make a difference in Ruby:
&lt;table class=&quot;CodeRay&quot;&gt;&lt;tr&gt;
  &lt;td title=&quot;click to toggle&quot; class=&quot;line_numbers&quot;&gt;&lt;pre&gt;1&lt;tt&gt;
&lt;/tt&gt;2&lt;tt&gt;
&lt;/tt&gt;3&lt;tt&gt;
&lt;/tt&gt;4&lt;tt&gt;
&lt;/tt&gt;&lt;strong&gt;5&lt;/strong&gt;&lt;tt&gt;
&lt;/tt&gt;6&lt;tt&gt;
&lt;/tt&gt;7&lt;tt&gt;
&lt;/tt&gt;8&lt;tt&gt;
&lt;/tt&gt;9&lt;tt&gt;
&lt;/tt&gt;&lt;/pre&gt;&lt;/td&gt;
  &lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;span class=&quot;er&quot;&gt;$&lt;/span&gt; irb&lt;tt&gt;
&lt;/tt&gt;&amp;gt;&amp;gt; &lt;span class=&quot;i&quot;&gt;5&lt;/span&gt; * &lt;span class=&quot;s&quot;&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;a&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;span class=&quot;co&quot;&gt;TypeError&lt;/span&gt;: &lt;span class=&quot;co&quot;&gt;String&lt;/span&gt; can&lt;span class=&quot;s&quot;&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;t be coerced into Fixnum&lt;tt&gt;
&lt;/tt&gt;  from (irb):1:in `*&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;  from (irb):&lt;span class=&quot;i&quot;&gt;1&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;&amp;gt;&amp;gt; &lt;span class=&quot;s&quot;&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;a&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt; * &lt;span class=&quot;i&quot;&gt;5&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;=&amp;gt; &lt;span class=&quot;s&quot;&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;aaaaa&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;&amp;gt;&amp;gt; &lt;tt&gt;
&lt;/tt&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;/tr&gt;&lt;/table&gt;

&lt;p&gt;The reason is quite simple &amp;mdash; everything in Ruby is an object.  The '&lt;code&gt;*&lt;/code&gt;' behaves differently when applied to different objects (and, in fact, can be overridden).  So, because the '&lt;code&gt;*&lt;/code&gt;' method as implemented for &lt;code&gt;Fixnum&lt;/code&gt; expects a number as its argument, and a &lt;code&gt;String&lt;/code&gt; isn't a number, it complains.  By the same token, the behaviour of '&lt;code&gt;*&lt;/code&gt;' for &lt;code&gt;String&lt;/code&gt; is for the string to repeat itself as many times as the argument specifies, it works.&lt;/p&gt;
          </content>  </entry>
  <entry xml:base="http://aetherical.com/">
    <author>
      <name>Matt Williams</name>
    </author>
    <id>tag:aetherical.com,2008-04-03:53</id>
    <published>2008-04-03T01:16:00Z</published>
    <updated>2008-04-03T01:17:19Z</updated>
    <category term="blog"/>
    <category term="syndicated"/>
    <link href="http://aetherical.com/2008/4/3/more-forth" rel="alternate" type="text/html"/>
    <title>More forth</title>
<content type="html">
            Yes, yesterday was April Fool's day.  But Forth and other stack-based languages (like postscript) are fun....
          </content>  </entry>
  <entry xml:base="http://aetherical.com/">
    <author>
      <name>Matt Williams</name>
    </author>
    <id>tag:aetherical.com,2008-04-01:52</id>
    <published>2008-04-01T13:47:00Z</published>
    <updated>2008-04-01T13:54:19Z</updated>
    <category term="blog"/>
    <category term="syndicated"/>
    <category term="forth"/>
    <category term="programming"/>
    <category term="ruby"/>
    <link href="http://aetherical.com/2008/4/1/reconsidering-forth" rel="alternate" type="text/html"/>
    <title>Reconsidering Forth</title>
<content type="html">
            &lt;p&gt;Recently I re-read Rick Cook's &lt;a href=&quot;http://www.amazon.com/Wizards-Bane-Rick-Cook/dp/0671698036/ref=pd_bbs_sr_1?ie=UTF8&amp;amp;s=books&amp;amp;qid=1207057925&amp;amp;sr=8-1&quot;&gt;Wizard's Bane&lt;/a&gt; and &lt;a href=&quot;http://www.amazon.com/Wizardry-Compiled-Cook/dp/0671720783/ref=pd_bbs_sr_1?ie=UTF8&amp;amp;s=books&amp;amp;qid=1207057960&amp;amp;sr=8-1&quot;&gt;The Wizardry Compiled&lt;/a&gt;.  I strongly recommend that series to anyone who wishes to be a serious developer.&lt;/p&gt;

&lt;p&gt;
And I realized that I'd been missing out on a lot of fun lately.  Ruby's become so dry and boring, it isn't funny.  I really miss the days of having a function named &lt;code&gt;corned_beef&lt;/code&gt; which uses such wondrous numbers as 65353.  And stack based programming really is da-bomb!  I remember all of the fun I used to have with it and have realized it's time to go back to it.
&lt;/p&gt;
          </content>  </entry>
</feed>
