<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type="text/css" href="/stylesheets/rss.css"?>
<rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:trackback="http://madskills.com/public/xml/rss/module/trackback/">
  <channel>
    <title>Toxic Elephant : Tag ruby, everything about ruby</title>
    <link>http://www.matijs.net/blog/tag/ruby.rss</link>
    <language>en-us</language>
    <ttl>40</ttl>
    <description>Don't bury it in your back yard!</description>
    <item>
      <title>The Arc Challenge</title>
      <description>&lt;p&gt;Hm, so &lt;a href="http://www.paulgraham.com/arc0.html"&gt;Arc is here&lt;/a&gt;, and Paul Graham gives &lt;a href="http://paulgraham.com/arcchallenge.html"&gt;the Arc challenge&lt;/a&gt;. The answer in Arc is short indeed. First, let&amp;#8217;s see an answer in Rails (loading a framework  is allowed according to the challenge), with &lt;code&gt;said_controller.rb&lt;/code&gt;:&lt;/p&gt;


&lt;div class="typocode"&gt;&lt;pre&gt;&lt;code class="typocode_ruby "&gt;&lt;span class="keyword"&gt;class &lt;/span&gt;&lt;span class="class"&gt;SaidController&lt;/span&gt; &lt;span class="punct"&gt;&amp;lt;&lt;/span&gt; &lt;span class="constant"&gt;ApplicationController&lt;/span&gt;
  &lt;span class="keyword"&gt;def &lt;/span&gt;&lt;span class="method"&gt;index&lt;/span&gt;&lt;span class="punct"&gt;;&lt;/span&gt; &lt;span class="keyword"&gt;end&lt;/span&gt;
  &lt;span class="keyword"&gt;def &lt;/span&gt;&lt;span class="method"&gt;click&lt;/span&gt;&lt;span class="punct"&gt;;&lt;/span&gt; &lt;span class="ident"&gt;session&lt;/span&gt;&lt;span class="punct"&gt;[&lt;/span&gt;&lt;span class="symbol"&gt;:it&lt;/span&gt;&lt;span class="punct"&gt;]&lt;/span&gt; &lt;span class="punct"&gt;=&lt;/span&gt; &lt;span class="ident"&gt;params&lt;/span&gt;&lt;span class="punct"&gt;['&lt;/span&gt;&lt;span class="string"&gt;what&lt;/span&gt;&lt;span class="punct"&gt;'];&lt;/span&gt; &lt;span class="keyword"&gt;end&lt;/span&gt;
  &lt;span class="keyword"&gt;def &lt;/span&gt;&lt;span class="method"&gt;show&lt;/span&gt;&lt;span class="punct"&gt;;&lt;/span&gt; &lt;span class="keyword"&gt;end&lt;/span&gt;
&lt;span class="keyword"&gt;end&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

	&lt;p&gt;and some templates, for the first page, &lt;code&gt;index.html.erb&lt;/code&gt;:&lt;/p&gt;


&lt;div class="typocode"&gt;&lt;pre&gt;&lt;code class="typocode_erb "&gt;&amp;lt;% form_tag '/said/click' do %&amp;gt;
  &amp;lt;%= text_field_tag 'what' %&amp;gt;
  &amp;lt;%= submit_tag %&amp;gt;
&amp;lt;% end %&amp;gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

	&lt;p&gt;second page, &lt;code&gt;click.html.erb&lt;/code&gt;:&lt;/p&gt;


&lt;div class="typocode"&gt;&lt;pre&gt;&lt;code class="typocode_erb "&gt;&amp;lt;%= link_to 'click here', {:action =&amp;gt; 'show'} %&amp;gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

	&lt;p&gt;third page, &lt;code&gt;show.html.erb&lt;/code&gt;:&lt;/p&gt;


&lt;div class="typocode"&gt;&lt;pre&gt;&lt;code class="typocode_erb "&gt;You said &amp;lt;%= session[:it] %&amp;gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

	&lt;p&gt;The Rails answer may be a little longer (although by how much is hard to say due to the different syntax&amp;#8212;is &lt;code&gt;end&lt;/code&gt; a token?), but it not a case of the same but longer.&lt;/p&gt;


	&lt;p&gt;First, the Rails version is in temporal order, the Arc version is not. Perhaps there&amp;#8217;s a way of reading the Arc version that makes this order natural, but right now, it looks confusing.&lt;/p&gt;


	&lt;p&gt;But the most striking difference is that it is based on a completely different philosophy of how web applications should be developed. The Arc answer is great if you want a web application based on continuations. The Rails answer is what you would use if you want to use &lt;span class="caps"&gt;REST&lt;/span&gt;.&lt;/p&gt;


	&lt;p&gt;I&amp;#8217;m definitely in the &lt;span class="caps"&gt;REST&lt;/span&gt; camp, which makes this example meaningless as a demonstration of Arc. It shows me that Arc can be used to write a short program that does something I don&amp;#8217;t want to do.&lt;/p&gt;


	&lt;p&gt;The ultimate question of course is whether brevity (in terms of number of tokens, not characters) is the single best metric for language power.&lt;/p&gt;


	&lt;p&gt;&lt;strong&gt;Update:&lt;/strong&gt; Someone wrote &lt;a href="http://arc-challenge.heroku.com/"&gt;a Ruby version&lt;/a&gt; that is about as short as the Arc version, uses the same paradigm, &lt;em&gt;and&lt;/em&gt; is in temporal order:&lt;/p&gt;


&lt;div class="typocode"&gt;&lt;pre&gt;&lt;code class="typocode_ruby "&gt;&lt;span class="keyword"&gt;def &lt;/span&gt;&lt;span class="method"&gt;said&lt;/span&gt;
  &lt;span class="ident"&gt;aform&lt;/span&gt;&lt;span class="punct"&gt;(&lt;/span&gt;&lt;span class="ident"&gt;input&lt;/span&gt;&lt;span class="punct"&gt;(&amp;quot;&lt;/span&gt;&lt;span class="string"&gt;foo&lt;/span&gt;&lt;span class="punct"&gt;&amp;quot;),&lt;/span&gt; &lt;span class="ident"&gt;submit&lt;/span&gt;&lt;span class="punct"&gt;)&lt;/span&gt; &lt;span class="punct"&gt;{&lt;/span&gt;
    &lt;span class="ident"&gt;w_link&lt;/span&gt;&lt;span class="punct"&gt;(&amp;quot;&lt;/span&gt;&lt;span class="string"&gt;click here&lt;/span&gt;&lt;span class="punct"&gt;&amp;quot;)&lt;/span&gt; &lt;span class="punct"&gt;{&lt;/span&gt;
      &lt;span class="punct"&gt;&amp;quot;&lt;/span&gt;&lt;span class="string"&gt;you said: &lt;span class="expr"&gt;#{arg :foo}&lt;/span&gt;&lt;/span&gt;&lt;span class="punct"&gt;&amp;quot;}}&lt;/span&gt;
&lt;span class="keyword"&gt;end&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;</description>
      <pubDate>Sun, 17 Feb 2008 21:14:00 +0000</pubDate>
      <guid isPermaLink="false">urn:uuid:9c770199-a783-4d9c-a432-b4439fbb79f1</guid>
      <author>blog@matijs.net (matijs)</author>
      <comments>http://www.matijs.net/blog/2008/02/17/the-arc-challenge#comments</comments>
      <category>software</category>
      <category>ruby</category>
      <category>arc</category>
      <category>language</category>
      <category>design</category>
      <category>continuations</category>
      <category>rest</category>
      <trackback:ping>http://www.matijs.net/blog/trackbacks?article_id=the-arc-challenge&amp;day=17&amp;month=02&amp;year=2008</trackback:ping>
      <link>http://www.matijs.net/blog/2008/02/17/the-arc-challenge</link>
    </item>
    <item>
      <title>Undressed Ruby</title>
      <description>&lt;p&gt;In Ruby, there is really no compile time. There is parse time, and then
there is run time. All class and method definitions are done at run time.&lt;/p&gt;


&lt;div class="typocode"&gt;&lt;pre&gt;&lt;code class="typocode_ruby "&gt;  &lt;span class="keyword"&gt;class &lt;/span&gt;&lt;span class="class"&gt;Foo&lt;/span&gt;
    &lt;span class="keyword"&gt;def &lt;/span&gt;&lt;span class="method"&gt;bar&lt;/span&gt;
      &lt;span class="ident"&gt;puts&lt;/span&gt; &lt;span class="punct"&gt;&amp;quot;&lt;/span&gt;&lt;span class="string"&gt;Zoo!&lt;/span&gt;&lt;span class="punct"&gt;&amp;quot;&lt;/span&gt;
    &lt;span class="keyword"&gt;end&lt;/span&gt;
  &lt;span class="keyword"&gt;end&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

	&lt;p&gt;is basically&lt;sup&gt;&lt;a href="#fn1"&gt;1&lt;/a&gt;&lt;/sup&gt;:&lt;/p&gt;


&lt;div class="typocode"&gt;&lt;pre&gt;&lt;code class="typocode_ruby "&gt;  &lt;span class="constant"&gt;Foo&lt;/span&gt; &lt;span class="punct"&gt;=&lt;/span&gt; &lt;span class="constant"&gt;Class&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;new&lt;/span&gt; &lt;span class="keyword"&gt;do&lt;/span&gt;
    &lt;span class="constant"&gt;self&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;define_method&lt;/span&gt;&lt;span class="punct"&gt;(&lt;/span&gt;&lt;span class="symbol"&gt;:bar&lt;/span&gt;&lt;span class="punct"&gt;)&lt;/span&gt; &lt;span class="keyword"&gt;do&lt;/span&gt;
      &lt;span class="ident"&gt;puts&lt;/span&gt; &lt;span class="punct"&gt;&amp;quot;&lt;/span&gt;&lt;span class="string"&gt;Zoo!&lt;/span&gt;&lt;span class="punct"&gt;&amp;quot;&lt;/span&gt;
    &lt;span class="keyword"&gt;end&lt;/span&gt;
  &lt;span class="keyword"&gt;end&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

	&lt;p&gt;See, we just removed the class and def keywords from Ruby. What else? Ah
yes, method calls. That&amp;#8217;s just sending messages. In fact, you can replace
any method call &lt;code&gt;foo.bar&lt;/code&gt; with &lt;code&gt;foo.send(:bar)&lt;/code&gt;, like so&lt;sup&gt;&lt;a href="#fn2"&gt;2&lt;/a&gt;&lt;/sup&gt;:&lt;/p&gt;


&lt;div class="typocode"&gt;&lt;pre&gt;&lt;code class="typocode_ruby "&gt;  &lt;span class="constant"&gt;Foo&lt;/span&gt; &lt;span class="punct"&gt;=&lt;/span&gt; &lt;span class="constant"&gt;Class&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;send&lt;/span&gt;&lt;span class="punct"&gt;(&lt;/span&gt;&lt;span class="symbol"&gt;:new&lt;/span&gt;&lt;span class="punct"&gt;)&lt;/span&gt; &lt;span class="keyword"&gt;do&lt;/span&gt;
    &lt;span class="constant"&gt;self&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;send&lt;/span&gt;&lt;span class="punct"&gt;(&lt;/span&gt;&lt;span class="symbol"&gt;:define_method&lt;/span&gt;&lt;span class="punct"&gt;,&lt;/span&gt; &lt;span class="symbol"&gt;:bar&lt;/span&gt;&lt;span class="punct"&gt;)&lt;/span&gt; &lt;span class="keyword"&gt;do&lt;/span&gt;
      &lt;span class="constant"&gt;self&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;send&lt;/span&gt;&lt;span class="punct"&gt;(&lt;/span&gt;&lt;span class="symbol"&gt;:puts&lt;/span&gt;&lt;span class="punct"&gt;,&lt;/span&gt; &lt;span class="punct"&gt;&amp;quot;&lt;/span&gt;&lt;span class="string"&gt;Zoo!&lt;/span&gt;&lt;span class="punct"&gt;&amp;quot;)&lt;/span&gt;
    &lt;span class="keyword"&gt;end&lt;/span&gt;
  &lt;span class="keyword"&gt;end&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

	&lt;p&gt;How much syntax can you remove like this? How far can Ruby be undressed? And can you come up with a macro system to put the clothes back on?&lt;/p&gt;


	&lt;p&gt;Some ingredients: &lt;a href="http://lists.warhead.org.uk/pipermail/iwe/2005-July/000130.html"&gt;Why list macros are cool&lt;/a&gt;,
&lt;a href="http://blog.zenspider.com/archives/2005/02/rubytoruby.html"&gt;RubyToRuby&lt;/a&gt;.&lt;/p&gt;


	&lt;p id="fn1"&gt;&lt;sup&gt;1&lt;/sup&gt; Actually, it&amp;#8217;s not the same, since the &lt;code&gt;define_method&lt;/code&gt; way creates a
closure, so you can do like
&lt;a href="http://project.ioni.st/post/1284#snippet_1284"&gt;this&lt;/a&gt;&lt;/p&gt;


	&lt;p id="fn2"&gt;&lt;sup&gt;2&lt;/sup&gt; Yes, I know I&amp;#8217;m using method call syntax here. But this way I do expose the message-passing view on OO that Ruby has. If you want, you can replace it with &lt;code&gt;send_message(object, method, *args)&lt;/code&gt;, and assume Ruby defines &lt;code&gt;send_message&lt;/code&gt; somewhere.&lt;/p&gt;</description>
      <pubDate>Sun, 14 Oct 2007 12:14:00 +0000</pubDate>
      <guid isPermaLink="false">urn:uuid:f4701d41-fb5f-4b51-864f-3c4d795b0061</guid>
      <author>blog@matijs.net (matijs)</author>
      <comments>http://www.matijs.net/blog/2007/10/14/undressed-ruby#comments</comments>
      <category>software</category>
      <category>ruby</category>
      <category>macros</category>
      <trackback:ping>http://www.matijs.net/blog/trackbacks?article_id=undressed-ruby&amp;day=14&amp;month=10&amp;year=2007</trackback:ping>
      <link>http://www.matijs.net/blog/2007/10/14/undressed-ruby</link>
    </item>
    <item>
      <title>A DSL for making SQL-like DSLs</title>
      <description>&lt;h3&gt;Setting the stage&lt;/h3&gt;


	&lt;p&gt;Some time ago, I came across
&lt;a href="http://www.rubyinside.com/sqldsl-a-ruby-way-to-build-sql-queries-421.html"&gt;&lt;span class="caps"&gt;SQLDSL&lt;/span&gt;&lt;/a&gt;,
a &lt;span class="caps"&gt;DSL&lt;/span&gt; for building &lt;span class="caps"&gt;SQL&lt;/span&gt; queries. The benefit of using a &lt;span class="caps"&gt;DSL&lt;/span&gt; over plain old
string concatenation is that syntax is checked before the database server
is hit. Unfortunately, &lt;span class="caps"&gt;SQLDSL&lt;/span&gt; does not deliver. It will happily accept&lt;/p&gt;


&lt;div class="typocode"&gt;&lt;pre&gt;&lt;code class="typocode_ruby "&gt;  &lt;span class="ident"&gt;q&lt;/span&gt; &lt;span class="punct"&gt;=&lt;/span&gt; &lt;span class="constant"&gt;Insert&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;into&lt;/span&gt;&lt;span class="punct"&gt;[&amp;quot;&lt;/span&gt;&lt;span class="string"&gt;frot&lt;/span&gt;&lt;span class="punct"&gt;&amp;quot;][&amp;quot;&lt;/span&gt;&lt;span class="string"&gt;zop&lt;/span&gt;&lt;span class="punct"&gt;&amp;quot;][&amp;quot;&lt;/span&gt;&lt;span class="string"&gt;blob&lt;/span&gt;&lt;span class="punct"&gt;&amp;quot;].&lt;/span&gt;&lt;span class="ident"&gt;values&lt;/span&gt;&lt;span class="punct"&gt;(&amp;quot;&lt;/span&gt;&lt;span class="string"&gt;kng&lt;/span&gt;&lt;span class="punct"&gt;&amp;quot;).&lt;/span&gt;&lt;span class="ident"&gt;values&lt;/span&gt;&lt;span class="punct"&gt;[&amp;quot;&lt;/span&gt;&lt;span class="string"&gt;kgn&lt;/span&gt;&lt;span class="punct"&gt;&amp;quot;]&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

	&lt;p&gt;resulting in&lt;/p&gt;


&lt;div class="typocode"&gt;&lt;pre&gt;&lt;code class="typocode_ruby "&gt;  &lt;span class="ident"&gt;q&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;to_sql&lt;/span&gt;
  &lt;span class="comment"&gt;# =&amp;gt; &amp;quot;insert into 'frot' (zop) (blob) values ('kng') values () (kgn)&amp;quot;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

	&lt;p&gt;which is hardly acceptable &lt;span class="caps"&gt;SQL&lt;/span&gt;.&lt;/p&gt;


	&lt;h3&gt;A metasolution&lt;/h3&gt;


	&lt;p&gt;The problem is that each chained call operates on the same class, so the
calls can be repeated, even when that&amp;#8217;s not appropriate. Instead, each step
in the building of the query should return an object of a different class,
having only methods appropriate at that stage. Something like this:&lt;/p&gt;


&lt;div class="typocode"&gt;&lt;pre&gt;&lt;code class="typocode_ruby "&gt;  &lt;span class="keyword"&gt;class &lt;/span&gt;&lt;span class="class"&gt;Insert&lt;/span&gt;
    &lt;span class="comment"&gt;# [...]&lt;/span&gt;
    &lt;span class="keyword"&gt;def &lt;/span&gt;&lt;span class="method"&gt;[]&lt;/span&gt;&lt;span class="punct"&gt;(*&lt;/span&gt;&lt;span class="ident"&gt;fields&lt;/span&gt;&lt;span class="punct"&gt;)&lt;/span&gt;
      &lt;span class="keyword"&gt;return&lt;/span&gt; &lt;span class="constant"&gt;InsertIntoFields&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;new&lt;/span&gt;&lt;span class="punct"&gt;(&lt;/span&gt;&lt;span class="attribute"&gt;@table&lt;/span&gt;&lt;span class="punct"&gt;,&lt;/span&gt; &lt;span class="ident"&gt;fields&lt;/span&gt;&lt;span class="punct"&gt;)&lt;/span&gt;
    &lt;span class="keyword"&gt;end&lt;/span&gt;
  &lt;span class="keyword"&gt;end&lt;/span&gt;

  &lt;span class="keyword"&gt;class &lt;/span&gt;&lt;span class="class"&gt;InsertIntoFields&lt;/span&gt;
    &lt;span class="comment"&gt;# [...]&lt;/span&gt;
    &lt;span class="keyword"&gt;def &lt;/span&gt;&lt;span class="method"&gt;values&lt;/span&gt;
      &lt;span class="constant"&gt;InsertIntoFieldsValuesPre&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;new&lt;/span&gt;&lt;span class="punct"&gt;(&lt;/span&gt;&lt;span class="attribute"&gt;@table&lt;/span&gt;&lt;span class="punct"&gt;,&lt;/span&gt; &lt;span class="attribute"&gt;@fields&lt;/span&gt;&lt;span class="punct"&gt;)&lt;/span&gt;
    &lt;span class="keyword"&gt;end&lt;/span&gt;
  &lt;span class="keyword"&gt;end&lt;/span&gt;

  &lt;span class="comment"&gt;# etc.&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

	&lt;p&gt;Of course, this quickly becomes tedious, with all the &lt;code&gt;initialize&lt;/code&gt; methods
having to be made, etc. Boring, boring. Let&amp;#8217;s do some metaprogramming.&lt;/p&gt;


	&lt;p&gt;First, I need a quick way to create a class with a certain number of
instance variables, that are set in the call to &lt;code&gt;new()&lt;/code&gt;. That sounds like
&lt;code&gt;Struct&lt;/code&gt;, but the classes that creates have too many methods that would
conflict with a &lt;span class="caps"&gt;DSL&lt;/span&gt; for &lt;span class="caps"&gt;SQL&lt;/span&gt; (like &lt;code&gt;values()&lt;/code&gt;). So instead, I took a small,
simplified part of &lt;a href="http://www.ruby-forum.com/topic/67759"&gt;Mauricio Fernandez alternative:
SuperClass&lt;/a&gt; (specifically, I didn&amp;#8217;t
want any accessors for the fields, or named parameters):&lt;/p&gt;


&lt;div class="typocode"&gt;&lt;pre&gt;&lt;code class="typocode_ruby "&gt;  &lt;span class="keyword"&gt;module &lt;/span&gt;&lt;span class="module"&gt;SuperClass&lt;/span&gt;
    &lt;span class="keyword"&gt;def &lt;/span&gt;&lt;span class="method"&gt;self.new&lt;/span&gt;&lt;span class="punct"&gt;(*&lt;/span&gt;&lt;span class="ident"&gt;fields&lt;/span&gt;&lt;span class="punct"&gt;,&lt;/span&gt; &lt;span class="punct"&gt;&amp;amp;&lt;/span&gt;&lt;span class="ident"&gt;blk&lt;/span&gt;&lt;span class="punct"&gt;)&lt;/span&gt;
      &lt;span class="ident"&gt;k&lt;/span&gt; &lt;span class="punct"&gt;=&lt;/span&gt; &lt;span class="constant"&gt;Class&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;new&lt;/span&gt; &lt;span class="keyword"&gt;do&lt;/span&gt;
    &lt;span class="attribute"&gt;@defined_instance_variables&lt;/span&gt; &lt;span class="punct"&gt;=&lt;/span&gt; &lt;span class="ident"&gt;fields&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;clone&lt;/span&gt;
    &lt;span class="keyword"&gt;class &lt;/span&gt;&lt;span class="punct"&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class="constant"&gt;self&lt;/span&gt;&lt;span class="punct"&gt;;&lt;/span&gt; &lt;span class="ident"&gt;attr_reader&lt;/span&gt; &lt;span class="symbol"&gt;:defined_instance_variables&lt;/span&gt; &lt;span class="keyword"&gt;end&lt;/span&gt;
    &lt;span class="ident"&gt;define_method&lt;/span&gt;&lt;span class="punct"&gt;(&lt;/span&gt;&lt;span class="symbol"&gt;:initialize&lt;/span&gt;&lt;span class="punct"&gt;)&lt;/span&gt; &lt;span class="keyword"&gt;do&lt;/span&gt; &lt;span class="punct"&gt;|*&lt;/span&gt;&lt;span class="ident"&gt;a&lt;/span&gt;&lt;span class="punct"&gt;|&lt;/span&gt;
      &lt;span class="keyword"&gt;if&lt;/span&gt; &lt;span class="ident"&gt;fields&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;size&lt;/span&gt; &lt;span class="punct"&gt;!=&lt;/span&gt; &lt;span class="ident"&gt;a&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;size&lt;/span&gt;
        &lt;span class="keyword"&gt;raise&lt;/span&gt; &lt;span class="constant"&gt;ArgumentError&lt;/span&gt;&lt;span class="punct"&gt;,&lt;/span&gt; &lt;span class="punct"&gt;&amp;quot;&lt;/span&gt;&lt;span class="string"&gt;wrong number of arguments (&lt;span class="expr"&gt;#{a.size}&lt;/span&gt; for &lt;span class="expr"&gt;#{fields.size}&lt;/span&gt;)&lt;/span&gt;&lt;span class="punct"&gt;&amp;quot;&lt;/span&gt;
      &lt;span class="keyword"&gt;else&lt;/span&gt;
        &lt;span class="ident"&gt;fields&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;each_with_index&lt;/span&gt; &lt;span class="punct"&gt;{|&lt;/span&gt;&lt;span class="ident"&gt;f&lt;/span&gt;&lt;span class="punct"&gt;,&lt;/span&gt;&lt;span class="ident"&gt;i&lt;/span&gt;&lt;span class="punct"&gt;|&lt;/span&gt; &lt;span class="ident"&gt;instance_variable_set&lt;/span&gt;&lt;span class="punct"&gt;(&amp;quot;&lt;/span&gt;&lt;span class="string"&gt;@&lt;span class="expr"&gt;#{f}&lt;/span&gt;&lt;/span&gt;&lt;span class="punct"&gt;&amp;quot;,&lt;/span&gt; &lt;span class="ident"&gt;a&lt;/span&gt;&lt;span class="punct"&gt;[&lt;/span&gt;&lt;span class="ident"&gt;i&lt;/span&gt;&lt;span class="punct"&gt;])}&lt;/span&gt;
      &lt;span class="keyword"&gt;end&lt;/span&gt;
    &lt;span class="keyword"&gt;end&lt;/span&gt;
      &lt;span class="keyword"&gt;end&lt;/span&gt;
      &lt;span class="ident"&gt;k&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;instance_eval&lt;/span&gt; &lt;span class="punct"&gt;&amp;amp;&lt;/span&gt;&lt;span class="ident"&gt;blk&lt;/span&gt; &lt;span class="keyword"&gt;if&lt;/span&gt; &lt;span class="ident"&gt;blk&lt;/span&gt;
      &lt;span class="ident"&gt;k&lt;/span&gt;
    &lt;span class="keyword"&gt;end&lt;/span&gt;
  &lt;span class="keyword"&gt;end&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

	&lt;p&gt;(Annoyingly, there&amp;#8217;s no way to dynamically create methods with arbitrary
arity, without resorting to &lt;code&gt;eval&lt;/code&gt;-ing a string.)&lt;/p&gt;


	&lt;p&gt;The heart of this metaprogramming is this module:&lt;/p&gt;


&lt;div class="typocode"&gt;&lt;pre&gt;&lt;code class="typocode_ruby "&gt;  &lt;span class="keyword"&gt;module &lt;/span&gt;&lt;span class="module"&gt;DSLChain&lt;/span&gt;
    &lt;span class="keyword"&gt;def &lt;/span&gt;&lt;span class="method"&gt;self.create&lt;/span&gt;&lt;span class="punct"&gt;(*&lt;/span&gt;&lt;span class="ident"&gt;fields&lt;/span&gt;&lt;span class="punct"&gt;,&lt;/span&gt; &lt;span class="punct"&gt;&amp;amp;&lt;/span&gt;&lt;span class="ident"&gt;blk&lt;/span&gt;&lt;span class="punct"&gt;)&lt;/span&gt;
      &lt;span class="ident"&gt;k&lt;/span&gt; &lt;span class="punct"&gt;=&lt;/span&gt; &lt;span class="constant"&gt;SuperClass&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;new&lt;/span&gt;&lt;span class="punct"&gt;(*&lt;/span&gt;&lt;span class="ident"&gt;fields&lt;/span&gt;&lt;span class="punct"&gt;)&lt;/span&gt;
      &lt;span class="ident"&gt;k&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;extend&lt;/span&gt;&lt;span class="punct"&gt;(&lt;/span&gt;&lt;span class="constant"&gt;DSLChain&lt;/span&gt;&lt;span class="punct"&gt;::&lt;/span&gt;&lt;span class="constant"&gt;Link&lt;/span&gt;&lt;span class="punct"&gt;)&lt;/span&gt;
      &lt;span class="ident"&gt;k&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;instance_eval&lt;/span&gt; &lt;span class="punct"&gt;&amp;amp;&lt;/span&gt;&lt;span class="ident"&gt;blk&lt;/span&gt; &lt;span class="keyword"&gt;if&lt;/span&gt; &lt;span class="ident"&gt;blk&lt;/span&gt;
      &lt;span class="ident"&gt;k&lt;/span&gt;
    &lt;span class="keyword"&gt;end&lt;/span&gt;
    &lt;span class="keyword"&gt;module &lt;/span&gt;&lt;span class="module"&gt;Link&lt;/span&gt;
      &lt;span class="keyword"&gt;def &lt;/span&gt;&lt;span class="method"&gt;add_step&lt;/span&gt;&lt;span class="punct"&gt;(&lt;/span&gt;&lt;span class="ident"&gt;func&lt;/span&gt;&lt;span class="punct"&gt;,&lt;/span&gt; &lt;span class="ident"&gt;field&lt;/span&gt;&lt;span class="punct"&gt;=&lt;/span&gt;&lt;span class="constant"&gt;nil&lt;/span&gt;&lt;span class="punct"&gt;)&lt;/span&gt;
    &lt;span class="ident"&gt;div&lt;/span&gt; &lt;span class="punct"&gt;=&lt;/span&gt; &lt;span class="ident"&gt;defined_instance_variables&lt;/span&gt;
    &lt;span class="ident"&gt;fields&lt;/span&gt; &lt;span class="punct"&gt;=&lt;/span&gt; &lt;span class="ident"&gt;div&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;clone&lt;/span&gt;
    &lt;span class="ident"&gt;fields&lt;/span&gt; &lt;span class="punct"&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class="ident"&gt;field&lt;/span&gt; &lt;span class="keyword"&gt;unless&lt;/span&gt; &lt;span class="ident"&gt;field&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;nil?&lt;/span&gt;
    &lt;span class="ident"&gt;n&lt;/span&gt; &lt;span class="punct"&gt;=&lt;/span&gt; &lt;span class="constant"&gt;DSLChain&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;create&lt;/span&gt;&lt;span class="punct"&gt;(*&lt;/span&gt;&lt;span class="ident"&gt;fields&lt;/span&gt;&lt;span class="punct"&gt;)&lt;/span&gt;

    &lt;span class="ident"&gt;define_method&lt;/span&gt; &lt;span class="ident"&gt;func&lt;/span&gt; &lt;span class="keyword"&gt;do&lt;/span&gt; &lt;span class="punct"&gt;|*&lt;/span&gt;&lt;span class="ident"&gt;a&lt;/span&gt;&lt;span class="punct"&gt;|&lt;/span&gt;
      &lt;span class="ident"&gt;vals&lt;/span&gt; &lt;span class="punct"&gt;=&lt;/span&gt; &lt;span class="punct"&gt;[]&lt;/span&gt;
      &lt;span class="ident"&gt;fields&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;each&lt;/span&gt; &lt;span class="keyword"&gt;do&lt;/span&gt;&lt;span class="punct"&gt;|&lt;/span&gt;&lt;span class="ident"&gt;f&lt;/span&gt;&lt;span class="punct"&gt;|&lt;/span&gt;
        &lt;span class="keyword"&gt;if&lt;/span&gt; &lt;span class="ident"&gt;div&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;include?&lt;/span&gt;&lt;span class="punct"&gt;(&lt;/span&gt;&lt;span class="ident"&gt;f&lt;/span&gt;&lt;span class="punct"&gt;)&lt;/span&gt;
          &lt;span class="ident"&gt;vals&lt;/span&gt; &lt;span class="punct"&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class="ident"&gt;instance_variable_get&lt;/span&gt;&lt;span class="punct"&gt;(&amp;quot;&lt;/span&gt;&lt;span class="string"&gt;@&lt;span class="expr"&gt;#{f}&lt;/span&gt;&lt;/span&gt;&lt;span class="punct"&gt;&amp;quot;)&lt;/span&gt;
        &lt;span class="keyword"&gt;end&lt;/span&gt;
      &lt;span class="keyword"&gt;end&lt;/span&gt;
      &lt;span class="ident"&gt;vals&lt;/span&gt; &lt;span class="punct"&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class="ident"&gt;a&lt;/span&gt; &lt;span class="keyword"&gt;if&lt;/span&gt; &lt;span class="ident"&gt;a&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;size&lt;/span&gt; &lt;span class="punct"&gt;&amp;gt;&lt;/span&gt; &lt;span class="number"&gt;0&lt;/span&gt;
      &lt;span class="ident"&gt;n&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;new&lt;/span&gt;&lt;span class="punct"&gt;(*(&lt;/span&gt;&lt;span class="ident"&gt;vals&lt;/span&gt;&lt;span class="punct"&gt;))&lt;/span&gt;
    &lt;span class="keyword"&gt;end&lt;/span&gt;
    &lt;span class="ident"&gt;n&lt;/span&gt;
      &lt;span class="keyword"&gt;end&lt;/span&gt;
    &lt;span class="keyword"&gt;end&lt;/span&gt;
  &lt;span class="keyword"&gt;end&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

	&lt;p&gt;&lt;code&gt;Stepper::Step#add_step(func, field)&lt;/code&gt; adds a method called &lt;code&gt;func&lt;/code&gt; that
creates an object of a new anonymous class, optionally adding a field
called &lt;code&gt;field&lt;/code&gt;.  It returns the new anonymous class, so theses calls can be
chained.&lt;/p&gt;


	&lt;p&gt;This means we can do the following:&lt;/p&gt;


&lt;div class="typocode"&gt;&lt;pre&gt;&lt;code class="typocode_ruby "&gt;  &lt;span class="comment"&gt;# Insert ...&lt;/span&gt;
  &lt;span class="constant"&gt;Insert&lt;/span&gt; &lt;span class="punct"&gt;=&lt;/span&gt; &lt;span class="constant"&gt;DSLChain&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;create&lt;/span&gt;&lt;span class="punct"&gt;(&lt;/span&gt;&lt;span class="symbol"&gt;:table&lt;/span&gt;&lt;span class="punct"&gt;)&lt;/span&gt; &lt;span class="keyword"&gt;do&lt;/span&gt;
    &lt;span class="comment"&gt;# Insert.into creates an instance of this class.&lt;/span&gt;
    &lt;span class="keyword"&gt;def &lt;/span&gt;&lt;span class="method"&gt;self.into&lt;/span&gt;&lt;span class="punct"&gt;(&lt;/span&gt;&lt;span class="ident"&gt;table&lt;/span&gt;&lt;span class="punct"&gt;)&lt;/span&gt;
      &lt;span class="constant"&gt;self&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;new&lt;/span&gt;&lt;span class="punct"&gt;(&lt;/span&gt;&lt;span class="ident"&gt;table&lt;/span&gt;&lt;span class="punct"&gt;)&lt;/span&gt;
    &lt;span class="keyword"&gt;end&lt;/span&gt;

    &lt;span class="comment"&gt;# Insert.into[fields].values[values]&lt;/span&gt;
    &lt;span class="constant"&gt;self&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;
      &lt;span class="ident"&gt;add_step&lt;/span&gt;&lt;span class="punct"&gt;(:[],&lt;/span&gt; &lt;span class="symbol"&gt;:fields&lt;/span&gt;&lt;span class="punct"&gt;).&lt;/span&gt;
      &lt;span class="ident"&gt;add_step&lt;/span&gt;&lt;span class="punct"&gt;(&lt;/span&gt;&lt;span class="symbol"&gt;:values&lt;/span&gt;&lt;span class="punct"&gt;).&lt;/span&gt;
      &lt;span class="ident"&gt;add_step&lt;/span&gt;&lt;span class="punct"&gt;(:[],&lt;/span&gt; &lt;span class="symbol"&gt;:values&lt;/span&gt;&lt;span class="punct"&gt;).&lt;/span&gt;&lt;span class="ident"&gt;class_eval&lt;/span&gt; &lt;span class="keyword"&gt;do&lt;/span&gt;
    &lt;span class="keyword"&gt;def &lt;/span&gt;&lt;span class="method"&gt;to_sql&lt;/span&gt;
      &lt;span class="ident"&gt;cn&lt;/span&gt; &lt;span class="punct"&gt;=&lt;/span&gt; &lt;span class="attribute"&gt;@table&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;column_names&lt;/span&gt;
      &lt;span class="attribute"&gt;@fields&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;each&lt;/span&gt; &lt;span class="punct"&gt;{|&lt;/span&gt;&lt;span class="ident"&gt;f&lt;/span&gt;&lt;span class="punct"&gt;|&lt;/span&gt; &lt;span class="ident"&gt;cn&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;include?&lt;/span&gt;&lt;span class="punct"&gt;(&lt;/span&gt;&lt;span class="ident"&gt;f&lt;/span&gt;&lt;span class="punct"&gt;)&lt;/span&gt; &lt;span class="keyword"&gt;or&lt;/span&gt; &lt;span class="keyword"&gt;raise&lt;/span&gt; &lt;span class="punct"&gt;&amp;quot;&lt;/span&gt;&lt;span class="string"&gt;Invalid field: &lt;span class="expr"&gt;#{f}&lt;/span&gt;&lt;/span&gt;&lt;span class="punct"&gt;&amp;quot;}&lt;/span&gt;
      &lt;span class="keyword"&gt;raise&lt;/span&gt; &lt;span class="punct"&gt;&amp;quot;&lt;/span&gt;&lt;span class="string"&gt;Incorrect number of values&lt;/span&gt;&lt;span class="punct"&gt;&amp;quot;&lt;/span&gt; &lt;span class="keyword"&gt;unless&lt;/span&gt; &lt;span class="attribute"&gt;@values&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;size&lt;/span&gt; &lt;span class="punct"&gt;==&lt;/span&gt; &lt;span class="attribute"&gt;@fields&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;size&lt;/span&gt;
      &lt;span class="ident"&gt;res&lt;/span&gt; &lt;span class="punct"&gt;=&lt;/span&gt; &lt;span class="punct"&gt;&amp;quot;&lt;/span&gt;&lt;span class="string"&gt;insert into &lt;span class="expr"&gt;#{@table.to_s.downcase}&lt;/span&gt; (&lt;/span&gt;&lt;span class="punct"&gt;&amp;quot;&lt;/span&gt;
      &lt;span class="ident"&gt;res&lt;/span&gt; &lt;span class="punct"&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class="attribute"&gt;@fields&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;join&lt;/span&gt;&lt;span class="punct"&gt;(&amp;quot;&lt;/span&gt;&lt;span class="string"&gt;, &lt;/span&gt;&lt;span class="punct"&gt;&amp;quot;)&lt;/span&gt;
      &lt;span class="ident"&gt;res&lt;/span&gt; &lt;span class="punct"&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class="punct"&gt;&amp;quot;&lt;/span&gt;&lt;span class="string"&gt;) values (&lt;/span&gt;&lt;span class="punct"&gt;&amp;quot;&lt;/span&gt;
      &lt;span class="ident"&gt;res&lt;/span&gt; &lt;span class="punct"&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class="attribute"&gt;@values&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;map&lt;/span&gt;&lt;span class="punct"&gt;{|&lt;/span&gt;&lt;span class="ident"&gt;v&lt;/span&gt;&lt;span class="punct"&gt;|&lt;/span&gt; &lt;span class="ident"&gt;v&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;to_sql&lt;/span&gt;&lt;span class="punct"&gt;}.&lt;/span&gt;&lt;span class="ident"&gt;join&lt;/span&gt;&lt;span class="punct"&gt;(&amp;quot;&lt;/span&gt;&lt;span class="string"&gt;, &lt;/span&gt;&lt;span class="punct"&gt;&amp;quot;)&lt;/span&gt;
      &lt;span class="ident"&gt;res&lt;/span&gt; &lt;span class="punct"&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class="punct"&gt;&amp;quot;&lt;/span&gt;&lt;span class="string"&gt;)&lt;/span&gt;&lt;span class="punct"&gt;&amp;quot;&lt;/span&gt;
      &lt;span class="ident"&gt;res&lt;/span&gt;
    &lt;span class="keyword"&gt;end&lt;/span&gt;
      &lt;span class="keyword"&gt;end&lt;/span&gt;
  &lt;span class="keyword"&gt;end&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

	&lt;p&gt;In the middle there, each call to &lt;code&gt;add_step(func, field)&lt;/code&gt; creates a new
intermediate anonymous class that results from a call to &lt;code&gt;func&lt;/code&gt; on the
previous one. The result is that after creating an &lt;code&gt;Insert&lt;/code&gt;
object with &lt;code&gt;Insert.into&lt;/code&gt;, the call sequence is forced to be&lt;/p&gt;


&lt;div class="typocode"&gt;&lt;pre&gt;&lt;code class="typocode_ruby "&gt;  &lt;span class="constant"&gt;Insert&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;into&lt;/span&gt;&lt;span class="punct"&gt;(&lt;/span&gt;&lt;span class="constant"&gt;SomeTable&lt;/span&gt;&lt;span class="punct"&gt;)[&amp;quot;&lt;/span&gt;&lt;span class="string"&gt;some&lt;/span&gt;&lt;span class="punct"&gt;&amp;quot;,&lt;/span&gt; &lt;span class="punct"&gt;&amp;quot;&lt;/span&gt;&lt;span class="string"&gt;column&lt;/span&gt;&lt;span class="punct"&gt;&amp;quot;,&lt;/span&gt; &lt;span class="punct"&gt;&amp;quot;&lt;/span&gt;&lt;span class="string"&gt;names&lt;/span&gt;&lt;span class="punct"&gt;&amp;quot;].&lt;/span&gt;
    &lt;span class="ident"&gt;values&lt;/span&gt;&lt;span class="punct"&gt;[&amp;quot;&lt;/span&gt;&lt;span class="string"&gt;these&lt;/span&gt;&lt;span class="punct"&gt;&amp;quot;,&lt;/span&gt; &lt;span class="punct"&gt;&amp;quot;&lt;/span&gt;&lt;span class="string"&gt;are&lt;/span&gt;&lt;span class="punct"&gt;&amp;quot;,&lt;/span&gt; &lt;span class="punct"&gt;&amp;quot;&lt;/span&gt;&lt;span class="string"&gt;values&lt;/span&gt;&lt;span class="punct"&gt;&amp;quot;].&lt;/span&gt;&lt;span class="ident"&gt;to_sql&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

	&lt;p&gt;Aside One: For this to work, &lt;code&gt;Insert.into&lt;/code&gt; takes some object that has a method
&lt;code&gt;column_names&lt;/code&gt;, like &lt;code&gt;ActiveRecord&lt;/code&gt; objects. I&amp;#8217;m also assuming appropriate
&lt;code&gt;to_sql&lt;/code&gt; methods to be defined on &lt;code&gt;String&lt;/code&gt; and &lt;code&gt;Numeric&lt;/code&gt;)&lt;/p&gt;


	&lt;p&gt;Aside Two: I changed the syntax a little bit from &lt;span class="caps"&gt;SQLDSL&lt;/span&gt;, since I like it better that
way.&lt;/p&gt;


	&lt;p&gt;The original example then results in:&lt;/p&gt;


&lt;div class="typocode"&gt;&lt;pre&gt;&lt;code class="typocode_ruby "&gt;  &lt;span class="constant"&gt;Insert&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;into&lt;/span&gt;&lt;span class="punct"&gt;(&lt;/span&gt;&lt;span class="constant"&gt;Frob&lt;/span&gt;&lt;span class="punct"&gt;)[&amp;quot;&lt;/span&gt;&lt;span class="string"&gt;id&lt;/span&gt;&lt;span class="punct"&gt;&amp;quot;][&amp;quot;&lt;/span&gt;&lt;span class="string"&gt;zonq&lt;/span&gt;&lt;span class="punct"&gt;&amp;quot;].&lt;/span&gt;&lt;span class="ident"&gt;values&lt;/span&gt;&lt;span class="punct"&gt;(&amp;quot;&lt;/span&gt;&lt;span class="string"&gt;kng&lt;/span&gt;&lt;span class="punct"&gt;&amp;quot;).&lt;/span&gt;&lt;span class="ident"&gt;values&lt;/span&gt;&lt;span class="punct"&gt;[&amp;quot;&lt;/span&gt;&lt;span class="string"&gt;kgn&lt;/span&gt;&lt;span class="punct"&gt;&amp;quot;]&lt;/span&gt;
  &lt;span class="comment"&gt;# =&amp;gt; undefined method `[]' for #&amp;lt;#&amp;lt;Class:0x30051330&amp;gt;:0x30050220 @fields=[&amp;quot;id&amp;quot;], @table=Frob&amp;gt; (NoMethodError)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

	&lt;h3&gt;More examples&lt;/h3&gt;


	&lt;p&gt;If you want two options, you can do this:&lt;/p&gt;


&lt;div class="typocode"&gt;&lt;pre&gt;&lt;code class="typocode_ruby "&gt;  &lt;span class="constant"&gt;Sample2&lt;/span&gt; &lt;span class="punct"&gt;=&lt;/span&gt; &lt;span class="constant"&gt;DSLChain&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;create&lt;/span&gt;&lt;span class="punct"&gt;(&lt;/span&gt;&lt;span class="symbol"&gt;:one&lt;/span&gt;&lt;span class="punct"&gt;)&lt;/span&gt; &lt;span class="keyword"&gt;do&lt;/span&gt;
    &lt;span class="ident"&gt;k&lt;/span&gt; &lt;span class="punct"&gt;=&lt;/span&gt; &lt;span class="constant"&gt;self&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;add_step&lt;/span&gt;&lt;span class="punct"&gt;(&lt;/span&gt;&lt;span class="symbol"&gt;:foo&lt;/span&gt;&lt;span class="punct"&gt;,&lt;/span&gt; &lt;span class="symbol"&gt;:two&lt;/span&gt;&lt;span class="punct"&gt;)&lt;/span&gt;
    &lt;span class="ident"&gt;k&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;add_step&lt;/span&gt;&lt;span class="punct"&gt;(&lt;/span&gt;&lt;span class="symbol"&gt;:bar&lt;/span&gt;&lt;span class="punct"&gt;,&lt;/span&gt; &lt;span class="symbol"&gt;:three&lt;/span&gt;&lt;span class="punct"&gt;).&lt;/span&gt;&lt;span class="ident"&gt;class_eval&lt;/span&gt; &lt;span class="keyword"&gt;do&lt;/span&gt;
      &lt;span class="keyword"&gt;def &lt;/span&gt;&lt;span class="method"&gt;to_s&lt;/span&gt;
        &lt;span class="punct"&gt;&amp;quot;&lt;/span&gt;&lt;span class="string"&gt;A bar: &lt;span class="expr"&gt;#{@one}&lt;/span&gt;, &lt;span class="expr"&gt;#{@two}&lt;/span&gt;, &lt;span class="expr"&gt;#{@three}&lt;/span&gt;&lt;/span&gt;&lt;span class="punct"&gt;&amp;quot;&lt;/span&gt;
      &lt;span class="keyword"&gt;end&lt;/span&gt;
    &lt;span class="keyword"&gt;end&lt;/span&gt;
    &lt;span class="ident"&gt;k&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;add_step&lt;/span&gt;&lt;span class="punct"&gt;(&lt;/span&gt;&lt;span class="symbol"&gt;:baz&lt;/span&gt;&lt;span class="punct"&gt;,&lt;/span&gt; &lt;span class="symbol"&gt;:four&lt;/span&gt;&lt;span class="punct"&gt;).&lt;/span&gt;&lt;span class="ident"&gt;class_eval&lt;/span&gt; &lt;span class="keyword"&gt;do&lt;/span&gt;
      &lt;span class="keyword"&gt;def &lt;/span&gt;&lt;span class="method"&gt;to_s&lt;/span&gt;
        &lt;span class="punct"&gt;&amp;quot;&lt;/span&gt;&lt;span class="string"&gt;A baz: &lt;span class="expr"&gt;#{@one}&lt;/span&gt;, &lt;span class="expr"&gt;#{@two}&lt;/span&gt;, &lt;span class="expr"&gt;#{@four}&lt;/span&gt;&lt;/span&gt;&lt;span class="punct"&gt;&amp;quot;&lt;/span&gt;
      &lt;span class="keyword"&gt;end&lt;/span&gt;
    &lt;span class="keyword"&gt;end&lt;/span&gt;
  &lt;span class="keyword"&gt;end&lt;/span&gt;

  &lt;span class="constant"&gt;Sample2&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;new&lt;/span&gt;&lt;span class="punct"&gt;(&amp;quot;&lt;/span&gt;&lt;span class="string"&gt;one&lt;/span&gt;&lt;span class="punct"&gt;&amp;quot;).&lt;/span&gt;&lt;span class="ident"&gt;foo&lt;/span&gt;&lt;span class="punct"&gt;(&amp;quot;&lt;/span&gt;&lt;span class="string"&gt;two&lt;/span&gt;&lt;span class="punct"&gt;&amp;quot;).&lt;/span&gt;&lt;span class="ident"&gt;bar&lt;/span&gt;&lt;span class="punct"&gt;(&amp;quot;&lt;/span&gt;&lt;span class="string"&gt;three&lt;/span&gt;&lt;span class="punct"&gt;&amp;quot;).&lt;/span&gt;&lt;span class="ident"&gt;to_s&lt;/span&gt;
  &lt;span class="comment"&gt;# =&amp;gt; A bar: one, two, three&lt;/span&gt;
  &lt;span class="constant"&gt;Sample2&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;new&lt;/span&gt;&lt;span class="punct"&gt;(&amp;quot;&lt;/span&gt;&lt;span class="string"&gt;one&lt;/span&gt;&lt;span class="punct"&gt;&amp;quot;).&lt;/span&gt;&lt;span class="ident"&gt;foo&lt;/span&gt;&lt;span class="punct"&gt;(&amp;quot;&lt;/span&gt;&lt;span class="string"&gt;two&lt;/span&gt;&lt;span class="punct"&gt;&amp;quot;).&lt;/span&gt;&lt;span class="ident"&gt;baz&lt;/span&gt;&lt;span class="punct"&gt;(&amp;quot;&lt;/span&gt;&lt;span class="string"&gt;four&lt;/span&gt;&lt;span class="punct"&gt;&amp;quot;).&lt;/span&gt;&lt;span class="ident"&gt;to_s&lt;/span&gt;
  &lt;span class="comment"&gt;# =&amp;gt; A baz: one, two, four&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

	&lt;h3&gt;Where to from here?&lt;/h3&gt;


	&lt;p&gt;This was mainly a proof-of-concept, of course. There is now a &lt;span class="caps"&gt;DSL&lt;/span&gt; to make
DSLs. I haven&amp;#8217;t even begun to create the &lt;span class="caps"&gt;DSL&lt;/span&gt; for the &lt;code&gt;select&lt;/code&gt; statement,
and &lt;code&gt;insert&lt;/code&gt; is far from complete. Doing the conditions of the &lt;code&gt;where&lt;/code&gt;
clause is yet another matter, although
&lt;a href="http://opensvn.csie.org/ezra/rails/plugins/dev/ez_where/"&gt;ez_where&lt;/a&gt; could
prove useful for that.&lt;/p&gt;


	&lt;p&gt;On the other hand, I may not get round to adding all those parts. The
metaprogramming was the best part, anyway.&lt;/p&gt;


	&lt;p&gt;On the gripping hand, wouldn&amp;#8217;t it be nicer to have a &lt;span class="caps"&gt;DSL&lt;/span&gt; that actually
looks like Ruby&amp;#8217;s array operations, such as &lt;code&gt;grep&lt;/code&gt; and &lt;code&gt;map&lt;/code&gt;? That would be
so much more beautiful.&lt;/p&gt;</description>
      <pubDate>Sat, 14 Apr 2007 14:42:00 +0000</pubDate>
      <guid isPermaLink="false">urn:uuid:16a27d7a-9e94-4671-8ea3-646c21e96904</guid>
      <author>blog@matijs.net (matijs)</author>
      <comments>http://www.matijs.net/blog/2007/04/14/a-dsl-for-making-sql-like-dsls#comments</comments>
      <category>software</category>
      <category>ruby</category>
      <category>metaprogramming</category>
      <category>dsl</category>
      <category>sql</category>
      <trackback:ping>http://www.matijs.net/blog/trackbacks?article_id=a-dsl-for-making-sql-like-dsls&amp;day=14&amp;month=04&amp;year=2007</trackback:ping>
      <link>http://www.matijs.net/blog/2007/04/14/a-dsl-for-making-sql-like-dsls</link>
    </item>
    <item>
      <title>I Want Cells-GTK for Ruby</title>
      <description>&lt;p&gt;For some applications, a spreadsheet is the perfect development
environment. The UI is a no-brainer, while the relations between the
different values is clearly visible, and changes are automatically
propagated from what could be called properties to derived values.&lt;/p&gt;


	&lt;p&gt;The problem is, of course, that you&amp;#8217;re missing out on the features a
programming language could offer. Macros are basically a dead end, unless
you like to solve user issues like &amp;#8216;It doesn&amp;#8217;t work because I disabled all
macros.&amp;#8217;&lt;/p&gt;


	&lt;p&gt;What I want is something that gives me this easy linking within a model and
between model and UI, but from withing Ruby. It is my prefered solution to
the &lt;a href="http://www.kryogenix.org/days/2006/07/06/gnome-2"&gt;Gnome on Rails&lt;/a&gt; problem.&lt;/p&gt;


	&lt;p&gt;&lt;a href="http://common-lisp.net/project/cells/"&gt;Cells for Common Lisp&lt;/a&gt; promises to
take care of the automatic propagation and dependencies between cells:&lt;/p&gt;


	&lt;blockquote&gt;
		&lt;p&gt;Cells is a mature, stable extension to &lt;span class="caps"&gt;CLOS&lt;/span&gt; that allows you to create
classes, the instances of which have slots whose values are determined by a
formula. Think of the slots as cells in a spreadsheet (get it?), and you&amp;#8217;ve
got the right idea. You can use any arbitrary Common Lisp expression to
specify the value of a cell. The Cells system takes care of tracking
dependencies among cells, and propagating values.&lt;/p&gt;
	&lt;/blockquote&gt;


	&lt;p&gt;That seems to take care of the automatic updating of derived values. The
second part is the no-brain-UI. What&amp;#8217;s needed for that is a dead-simple way
to link settable values to input widgets (text boxes, spin buttons, etc.),
and to link derived cell values to labels. By dead-simple I mean that it
should be done in at most one line per widget/value pair.&lt;/p&gt;


	&lt;p&gt;It seems for that part, the solution would be to use
&lt;a href="http://common-lisp.net/project/cells-gtk/"&gt;cells-gtk&lt;/a&gt;:&lt;/p&gt;


	&lt;blockquote&gt;
		&lt;p&gt;Cells transparently link &lt;span class="caps"&gt;GUI&lt;/span&gt; elements with each other and the
application model to greatly simplify development of rich interfaces. Cells
also automate how Lisp &lt;span class="caps"&gt;GUI&lt;/span&gt; instances drive their &lt;span class="caps"&gt;GTK&lt;/span&gt;+ counterparts.&lt;/p&gt;
	&lt;/blockquote&gt;


	&lt;p&gt;Sounds great!&lt;/p&gt;


	&lt;p&gt;The problem (for me at least) is that this is all in Lisp, and I don&amp;#8217;t know
Lisp yet. So, I want this, but in Ruby (since that&amp;#8217;s the language I like to
use most right now). Some basic ingredients are already there: We can use
blocks as formulas for the derived values, and there&amp;#8217;s the Observable
module. Also, Ruby has bindings for Gtk+.&lt;/p&gt;


	&lt;p&gt;I have some more wishes, but they&amp;#8217;re mostly about Gtk+, so I leave those
till later.&lt;/p&gt;</description>
      <pubDate>Mon, 22 Jan 2007 13:21:00 +0000</pubDate>
      <guid isPermaLink="false">urn:uuid:d91127bb-b776-4664-a600-96d168999ba1</guid>
      <author>blog@matijs.net (matijs)</author>
      <comments>http://www.matijs.net/blog/2007/01/22/i-want-cells-gtk-for-ruby#comments</comments>
      <category>software</category>
      <category>ruby</category>
      <category>lisp</category>
      <trackback:ping>http://www.matijs.net/blog/trackbacks?article_id=i-want-cells-gtk-for-ruby&amp;day=22&amp;month=01&amp;year=2007</trackback:ping>
      <link>http://www.matijs.net/blog/2007/01/22/i-want-cells-gtk-for-ruby</link>
    </item>
    <item>
      <title>Skipping Python for Ruby</title>
      <description>&lt;p&gt;&lt;a href="http://withoutane.com/rants/2007/01/embrace-the-heresy"&gt;Without an e writes&lt;/a&gt;:&lt;/p&gt;


	&lt;blockquote&gt;
		&lt;p&gt;Well, ruby just isn&amp;#8217;t that much better than python. If I&amp;#8217;m going to
  relearn everything, why would I bother with ruby? Why not just jump
  straight to lisp?&lt;/p&gt;
	&lt;/blockquote&gt;


	&lt;p&gt;I can really appreciate this argument, since it resonates with my reasons
for not learning Python: I knew Perl, and was doing most of my programming
in it, making nicely structured, readable, object-oriented programs. To me,
Python didn&amp;#8217;t seem like such a big step forward: It&amp;#8217;s like a Perl with
enforced readability.&lt;/p&gt;


	&lt;p&gt;And then came Ruby.&lt;/p&gt;


	&lt;p&gt;My introduction to Ruby was not through Rails, but through reading the
online version of the Pickaxe Book. After reading the first chapter, I was
sold. Here was a language that truly embraced object-orientation, and gave
access to all kinds of interesting abstractions that I had only vaguely
heard of (such as coroutines). There also was a pleasant lack of
boilerplate.&lt;/p&gt;


	&lt;p&gt;So to me, Ruby is that much better than Perl, whereas Python is not. I
wouldn&amp;#8217;t know if I agree that Ruby is not that much better than Python, but
at least I can understand the argument. Ruby is certainly no Lisp, although &lt;a href="http://www.randomhacks.net/articles/2005/12/03/why-ruby-is-an-acceptable-lisp"&gt;it comes close&lt;/a&gt;.&lt;/p&gt;


	&lt;p&gt;So what&amp;#8217;s next? Lisp&amp;#8217;s features certainly look appealing, giving basically
the pinnacle of power of abstraction, in exchange for slightly unappealing
syntax. I believe the syntax can be overcome, so my next language to learn
may well be a Lisp. Which Lisp is still an open question. On the other
hand, there are interesting languages like Erlang, ML and the like.&lt;/p&gt;


	&lt;p&gt;[Incidentally, Without an e is the creator of
&lt;a href="http://scarletlambda.org/"&gt;Scarlet Lambda&lt;/a&gt;, which
is roughly a web framework written in, or at least used with, a functional
style of programming in Python, with a Lisp-like syntax. Wow.]&lt;/p&gt;</description>
      <pubDate>Thu, 18 Jan 2007 18:59:00 +0000</pubDate>
      <guid isPermaLink="false">urn:uuid:b1e959c7-9a2b-48f9-923a-984f09a47bde</guid>
      <author>blog@matijs.net (matijs)</author>
      <comments>http://www.matijs.net/blog/2007/01/18/skipping-python-for-ruby#comments</comments>
      <category>software</category>
      <category>ruby</category>
      <category>lisp</category>
      <category>programming</category>
      <category>python</category>
      <trackback:ping>http://www.matijs.net/blog/trackbacks?article_id=skipping-python-for-ruby&amp;day=18&amp;month=01&amp;year=2007</trackback:ping>
      <link>http://www.matijs.net/blog/2007/01/18/skipping-python-for-ruby</link>
    </item>
  </channel>
</rss>
