<?xml version="1.0" encoding="UTF-8"?>
<feed xml:lang="en-US" xmlns="http://www.w3.org/2005/Atom">
  <title>PaulBarry.com - Practical Common Ruby - Do you really need macros?</title>
  <subtitle type="html">My thoughts, ideas, questions and concerns on technology, sports, music and life</subtitle>
  <id>tag:paulbarry.com,2007:Paulbarry.com</id>
  <generator uri="http://www.paulbarry.com" version="3.0">PaulBarry.com</generator>
  <link href="http://paulbarry.com/xml/atom/article/4849/feed.xml" rel="self" type="application/atom+xml"/>
  <link href="http://paulbarry.com/articles/2007/11/26/practical-common-ruby-do-you-really-need-macros" rel="alternate" type="text/html"/>

  <updated>2008-11-06T19:05:25-05:00</updated>
  <entry>
    <author>
      <name>Paul Barry</name>
      <email>mail@paulbarry.com</email>
    </author>
    <id>urn:uuid:432934cf-eabc-45c7-a238-e951ad3f7543</id>

    <published>2007-11-26T23:16:17-05:00</published>
    <updated>2007-11-26T23:16:17-05:00</updated>
    <title type="html">Practical Common Ruby - Do you really need macros?</title>
    <link href="http://paulbarry.com/articles/2007/11/26/practical-common-ruby-do-you-really-need-macros" rel="alternate" type="text/html"/>

    <category term="technology" scheme="http://paulbarry.com/articles/category/technology" label="Technology"/>
        <category term="macros" scheme="http://paulbarry.com/articles/tag/macros"/>
    <category term="Ruby" scheme="http://paulbarry.com/articles/tag/ruby"/>
    <category term="lisp" scheme="http://paulbarry.com/articles/tag/lisp"/>
        <summary type="html">&lt;p&gt;&lt;a href=&quot;http://www.gigamonkeys.com/book/practical-building-a-unit-test-framework.html&quot;&gt;Chapter 9&lt;/a&gt; of &lt;a href=&quot;http://www.gigamonkeys.com/book&quot;&gt;Practical Common Lisp&lt;/a&gt; has us diving deeper into Lisp macros by creating a test framework, which I will of course, try to port to Ruby.  The more I continue to work on this, the more I&apos;m convinced this is a great way to learn a new language.&lt;/p&gt;

&lt;p&gt;First off, you are forced to digest the examples that you convert, because you have to think about what the code is doing and how you would do it in the language that you know.  The bonus payoff is that you now have code in both languages to compare, so you can evaluate the two languages side-by-side.  So on with the code.&lt;/p&gt;

&lt;p&gt;Right off bat we run into a small problem, which is that you can&apos;t have &quot;+&quot; or &quot;*&quot; characters in the name of a method in Ruby.  That&apos;s ok, we can work around that:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;def test_plus
  1 + 2 == 3 &amp;amp;&amp;amp;
  1 + 2 + 3 == 6 &amp;amp;&amp;amp;
  -1 + -3 == -4
end
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Which works:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;paulbarry@paulbarry: ~/projects/practical_common_ruby $ irb
irb(main):001:0&amp;gt; load &apos;chap9.rb&apos;
=&amp;gt; true
irb(main):002:0&amp;gt; test_plus
=&amp;gt; true
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Next we tackle the version with test case info:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;def test_plus
  puts &quot;#{eval(&quot;1 + 2 == 3&quot;) ? &apos;pass&apos; : &apos;FAIL&apos;} ... 1 + 2 == 3&quot;
  puts &quot;#{eval(&quot;1 + 2 + 3 == 6&quot;) ? &apos;pass&apos; : &apos;FAIL&apos;} ... 1 + 2 + 3 == 6&quot;
  puts &quot;#{eval(&quot;-1 + -3 == -4&quot;) ? &apos;pass&apos; : &apos;FAIL&apos;} ... -1 + -3 == -4&quot;
end
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Now a little refactoring by adding report_result:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;def report_result(result, form)
  puts &quot;#{result ? &apos;pass&apos; : &apos;FAIL&apos;} ... #{form}&quot;
end

def test_plus
  report_result(1 + 2 == 3, &quot;1 + 2 == 3&quot;)
  report_result(1 + 2 + 3 == 6, &quot;1 + 2 + 3 == 6&quot;)
  report_result(-1 + -3 == -4, &quot;-1 + -3 == -4&quot;)
end
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;This isn&apos;t really very clean, first of all because of the obvious duplication of the actual code and the name, but secondly, we have our code as an argument to the &lt;code&gt;report_result&lt;/code&gt; method.  This works in lisp, because everything is just an expression, but in Ruby, once this method gets more complicated, this is going to be ugly.  So I&apos;m going to refactor &lt;code&gt;report_result&lt;/code&gt; to allow for two conditions.  The first just takes the code as a string and evals it, using the code as the &quot;name&quot; of the test.  Second, the string is the &quot;name&quot; and the block has the code.  I think this makes sense, because even in lisp, if the code is some long, multiline expression, you aren&apos;t going to want that to be the name of the test, you are going to want to supply a shorter, more descriptive name.&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;def report_result(test)
  if block_given?
    result = yield
  else  
    result = eval(test)
  end
  puts &quot;#{result ? &apos;pass&apos; : &apos;FAIL&apos;} ... #{test}&quot;
end

def test_plus
  report_result &quot;1 + 2 == 3&quot;
  report_result &quot;1 + 2 + 3 == 6&quot;
  report_result &quot;adding negative numbers&quot; do
    -1 + -3 == -4
  end
end
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;The next refactoring is to define a check method that takes multiple &quot;tests&quot; and prints the results of each one, mainly because the repeated calls to &lt;code&gt;report_result&lt;/code&gt; is considered unappealing.  I&apos;m not sure there is a particularly cleaner version of this in Ruby, but here&apos;s the best I&apos;ve got:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;def report_result(test)
  if block_given?
    result = yield
  else  
    result = eval(test)
  end
  puts &quot;#{result ? &apos;pass&apos; : &apos;FAIL&apos;} ... #{test}&quot;
end

def check(*tests)
  tests.each do |t|
    if t.is_a?(Hash)
      report_result t.keys.first, &amp;amp;t.values.first
    else
      report_result t
    end
  end
end

def test_plus
  check(
    &quot;1 + 2 == 3&quot;,
    &quot;1 + 2 + 3 == 6&quot;,
    &quot;adding negative numbers&quot; =&amp;gt; lambda{ -1 + -3 == -4 }
  )
end
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;I found this &lt;a href=&quot;http://eli.thegreenplace.net/2006/04/18/understanding-ruby-blocks-procs-and-methods/&quot;&gt;tutorial on Ruby&apos;s Procs and Blocks&lt;/a&gt; to be helpful while working on this.  In reality, I think most Ruby programmers would stick to the original version of &lt;code&gt;test_plus&lt;/code&gt; over this version that uses Hash and Lambdas, but I&apos;ll stick with this one because it&apos;s closer to the actual code in the example.  A couple of small changes give us the ability to track if the test has a failure:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;def report_result(test)
  if block_given?
    result = yield
  else  
    result = eval(test)
  end
  puts &quot;#{result ? &apos;pass&apos; : &apos;FAIL&apos;} ... #{test}&quot;
  result
end

module Enumerable
  def each?
    result = true
    each do |i|
      result = false unless yield(i)
    end
    result
  end
end

def check(*tests)
  tests.each? do |t|
    if t.is_a?(Hash)
      report_result(t.keys.first, &amp;amp;t.values.first)
    else
      report_result(t)
    end
  end
end
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;I choose to implement the &lt;code&gt;combine_results&lt;/code&gt; function from the example as an iterator called &lt;code&gt;each?&lt;/code&gt; mixed-in to Enumerable, so that we can call it in the idiomatic Ruby way &lt;code&gt;tests.each?&lt;/code&gt;.  &lt;code&gt;each?&lt;/code&gt; is similar to the &lt;code&gt;all?&lt;/code&gt; method that already exists in Enumerable, except that &lt;code&gt;all?&lt;/code&gt; short-circuits and stops iterating through over the items once the block evaluates to false.  We want to always perform the block on each item in the enumerable, and then return false if any are false.  I choose to name it &lt;code&gt;each?&lt;/code&gt; rather than &lt;code&gt;combine_results&lt;/code&gt; because it&apos;s more descriptive, more Rubyish.  I&apos;m actually kind of surprised Ruby doesn&apos;t have a method like that.&lt;/p&gt;

&lt;p&gt;Now this next bit require dynamic variables.  This is a new concept for me and I have to say, it is pretty cool.  The bad news?  Ruby doesn&apos;t have dynamic variables :(.  The good news?  We can fake it.  Just download &lt;a href=&quot;http://chneukirchen.org/blog/archive/2005/04/dynamic-variables-in-ruby.html&quot;&gt;this code&lt;/a&gt; and we are ready to go.  We add in a line to define the variable:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;Dynamic.variable :test_name
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Then we add it into our test method.  We also have to do a little finagling to get them to still return the right value:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;def test_plus
  result = false
  Dynamic.let :test_name =&amp;gt; &apos;test_plus&apos; do
    result = check(
      &quot;1 + 2 == 3&quot;,
      &quot;1 + 2 + 33 == 6&quot;,
      &quot;adding negative numbers&quot; =&amp;gt; lambda{ -1 + -3 == -4 }
    )
  end
  result
end

def test_times
  result = false
  Dynamic.let :test_name =&amp;gt; &apos;test_times&apos; do
    result = check(
      &quot;2 * 2 == 4&quot;,
      &quot;3 * 5 == 15&quot;
    )
  end
  result
end
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Lastly we just add the dynamic variable to the print statement in report_result:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;def report_result(test)
  if block_given?
    result = yield
  else  
    result = eval(test)
  end
  puts &quot;#{result ? &apos;pass&apos; : &apos;FAIL&apos;} ... #{Dynamic.test_name}: #{test}&quot;
  result
end
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;So now we want to clean up this redundant test code, but alas, Ruby does not have macros.  Here we go again, coming pretty close.  Define a method we will use to define tests:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;def test(name)
  test_name = &quot;test_#{name}&quot;
  method = lambda do
    result = false
    Dynamic.let :test_name =&amp;gt; &quot;#{Dynamic.test_name} #{test_name}&quot; do
      result = yield
    end
    result
  end    
  Object.send(:define_method, test_name, method)
end
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;I&apos;m not even going to try to explain how this code works.  This is pretty dense.  I&apos;m not sure if it is more or less dense than the Lisp code.  Now that we have our Ruby &quot;macro&quot; created, we can define our tests like this:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;test &quot;plus&quot; do
  check(
    &quot;1 + 2 == 3&quot;,
    &quot;1 + 2 + 3 == 6&quot;,
    &quot;adding negative numbers&quot; =&amp;gt; lambda{ -1 + -3 == -4 }
  )
end

test &quot;times&quot; do 
  check(
    &quot;2 * 2 == 4&quot;,
    &quot;3 * 5 == 15&quot;
  )
end

test &quot;arithmetic&quot; do
  %w{test_plus test_times}.each? do |t|
    send t
  end
end

test &quot;math&quot; do
  test_arithmetic
end
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;And voila, we have a feature complete version of the test framework in Ruby:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;irb(main):096:0&amp;gt; test_math
pass ...  test_math test_arithmetic test_plus: 1 + 2 == 3
pass ...  test_math test_arithmetic test_plus: 1 + 2 + 3 == 6
pass ...  test_math test_arithmetic test_plus: adding negative numbers
pass ...  test_math test_arithmetic test_times: 2 * 2 == 4
pass ...  test_math test_arithmetic test_times: 3 * 5 == 15
=&amp;gt; true
irb(main):097:0&amp;gt; test_arithmetic
pass ...  test_arithmetic test_plus: 1 + 2 == 3
pass ...  test_arithmetic test_plus: 1 + 2 + 3 == 6
pass ...  test_arithmetic test_plus: adding negative numbers
pass ...  test_arithmetic test_times: 2 * 2 == 4
pass ...  test_arithmetic test_times: 3 * 5 == 15
=&amp;gt; true
irb(main):098:0&amp;gt; test_plus
pass ...  test_plus: 1 + 2 == 3
pass ...  test_plus: 1 + 2 + 3 == 6
pass ...  test_plus: adding negative numbers
=&amp;gt; true
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;So in conclusion, macros are one feature of Lisp that have no direct equivalent in Ruby, but you can define methods that define methods, which is pretty close to what macros do.  Given Ruby&apos;s metaprogramming features like eval, send, and define_method, etc., Do you really need macros?.  The search for the answer continues...&lt;/p&gt;
</summary>
    <content type="html">&lt;p&gt;&lt;a href=&quot;http://www.gigamonkeys.com/book/practical-building-a-unit-test-framework.html&quot;&gt;Chapter 9&lt;/a&gt; of &lt;a href=&quot;http://www.gigamonkeys.com/book&quot;&gt;Practical Common Lisp&lt;/a&gt; has us diving deeper into Lisp macros by creating a test framework, which I will of course, try to port to Ruby.  The more I continue to work on this, the more I&apos;m convinced this is a great way to learn a new language.&lt;/p&gt;

&lt;p&gt;First off, you are forced to digest the examples that you convert, because you have to think about what the code is doing and how you would do it in the language that you know.  The bonus payoff is that you now have code in both languages to compare, so you can evaluate the two languages side-by-side.  So on with the code.&lt;/p&gt;

&lt;p&gt;Right off bat we run into a small problem, which is that you can&apos;t have &quot;+&quot; or &quot;*&quot; characters in the name of a method in Ruby.  That&apos;s ok, we can work around that:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;def test_plus
  1 + 2 == 3 &amp;amp;&amp;amp;
  1 + 2 + 3 == 6 &amp;amp;&amp;amp;
  -1 + -3 == -4
end
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Which works:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;paulbarry@paulbarry: ~/projects/practical_common_ruby $ irb
irb(main):001:0&amp;gt; load &apos;chap9.rb&apos;
=&amp;gt; true
irb(main):002:0&amp;gt; test_plus
=&amp;gt; true
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Next we tackle the version with test case info:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;def test_plus
  puts &quot;#{eval(&quot;1 + 2 == 3&quot;) ? &apos;pass&apos; : &apos;FAIL&apos;} ... 1 + 2 == 3&quot;
  puts &quot;#{eval(&quot;1 + 2 + 3 == 6&quot;) ? &apos;pass&apos; : &apos;FAIL&apos;} ... 1 + 2 + 3 == 6&quot;
  puts &quot;#{eval(&quot;-1 + -3 == -4&quot;) ? &apos;pass&apos; : &apos;FAIL&apos;} ... -1 + -3 == -4&quot;
end
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Now a little refactoring by adding report_result:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;def report_result(result, form)
  puts &quot;#{result ? &apos;pass&apos; : &apos;FAIL&apos;} ... #{form}&quot;
end

def test_plus
  report_result(1 + 2 == 3, &quot;1 + 2 == 3&quot;)
  report_result(1 + 2 + 3 == 6, &quot;1 + 2 + 3 == 6&quot;)
  report_result(-1 + -3 == -4, &quot;-1 + -3 == -4&quot;)
end
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;This isn&apos;t really very clean, first of all because of the obvious duplication of the actual code and the name, but secondly, we have our code as an argument to the &lt;code&gt;report_result&lt;/code&gt; method.  This works in lisp, because everything is just an expression, but in Ruby, once this method gets more complicated, this is going to be ugly.  So I&apos;m going to refactor &lt;code&gt;report_result&lt;/code&gt; to allow for two conditions.  The first just takes the code as a string and evals it, using the code as the &quot;name&quot; of the test.  Second, the string is the &quot;name&quot; and the block has the code.  I think this makes sense, because even in lisp, if the code is some long, multiline expression, you aren&apos;t going to want that to be the name of the test, you are going to want to supply a shorter, more descriptive name.&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;def report_result(test)
  if block_given?
    result = yield
  else  
    result = eval(test)
  end
  puts &quot;#{result ? &apos;pass&apos; : &apos;FAIL&apos;} ... #{test}&quot;
end

def test_plus
  report_result &quot;1 + 2 == 3&quot;
  report_result &quot;1 + 2 + 3 == 6&quot;
  report_result &quot;adding negative numbers&quot; do
    -1 + -3 == -4
  end
end
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;The next refactoring is to define a check method that takes multiple &quot;tests&quot; and prints the results of each one, mainly because the repeated calls to &lt;code&gt;report_result&lt;/code&gt; is considered unappealing.  I&apos;m not sure there is a particularly cleaner version of this in Ruby, but here&apos;s the best I&apos;ve got:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;def report_result(test)
  if block_given?
    result = yield
  else  
    result = eval(test)
  end
  puts &quot;#{result ? &apos;pass&apos; : &apos;FAIL&apos;} ... #{test}&quot;
end

def check(*tests)
  tests.each do |t|
    if t.is_a?(Hash)
      report_result t.keys.first, &amp;amp;t.values.first
    else
      report_result t
    end
  end
end

def test_plus
  check(
    &quot;1 + 2 == 3&quot;,
    &quot;1 + 2 + 3 == 6&quot;,
    &quot;adding negative numbers&quot; =&amp;gt; lambda{ -1 + -3 == -4 }
  )
end
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;I found this &lt;a href=&quot;http://eli.thegreenplace.net/2006/04/18/understanding-ruby-blocks-procs-and-methods/&quot;&gt;tutorial on Ruby&apos;s Procs and Blocks&lt;/a&gt; to be helpful while working on this.  In reality, I think most Ruby programmers would stick to the original version of &lt;code&gt;test_plus&lt;/code&gt; over this version that uses Hash and Lambdas, but I&apos;ll stick with this one because it&apos;s closer to the actual code in the example.  A couple of small changes give us the ability to track if the test has a failure:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;def report_result(test)
  if block_given?
    result = yield
  else  
    result = eval(test)
  end
  puts &quot;#{result ? &apos;pass&apos; : &apos;FAIL&apos;} ... #{test}&quot;
  result
end

module Enumerable
  def each?
    result = true
    each do |i|
      result = false unless yield(i)
    end
    result
  end
end

def check(*tests)
  tests.each? do |t|
    if t.is_a?(Hash)
      report_result(t.keys.first, &amp;amp;t.values.first)
    else
      report_result(t)
    end
  end
end
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;I choose to implement the &lt;code&gt;combine_results&lt;/code&gt; function from the example as an iterator called &lt;code&gt;each?&lt;/code&gt; mixed-in to Enumerable, so that we can call it in the idiomatic Ruby way &lt;code&gt;tests.each?&lt;/code&gt;.  &lt;code&gt;each?&lt;/code&gt; is similar to the &lt;code&gt;all?&lt;/code&gt; method that already exists in Enumerable, except that &lt;code&gt;all?&lt;/code&gt; short-circuits and stops iterating through over the items once the block evaluates to false.  We want to always perform the block on each item in the enumerable, and then return false if any are false.  I choose to name it &lt;code&gt;each?&lt;/code&gt; rather than &lt;code&gt;combine_results&lt;/code&gt; because it&apos;s more descriptive, more Rubyish.  I&apos;m actually kind of surprised Ruby doesn&apos;t have a method like that.&lt;/p&gt;

&lt;p&gt;Now this next bit require dynamic variables.  This is a new concept for me and I have to say, it is pretty cool.  The bad news?  Ruby doesn&apos;t have dynamic variables :(.  The good news?  We can fake it.  Just download &lt;a href=&quot;http://chneukirchen.org/blog/archive/2005/04/dynamic-variables-in-ruby.html&quot;&gt;this code&lt;/a&gt; and we are ready to go.  We add in a line to define the variable:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;Dynamic.variable :test_name
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Then we add it into our test method.  We also have to do a little finagling to get them to still return the right value:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;def test_plus
  result = false
  Dynamic.let :test_name =&amp;gt; &apos;test_plus&apos; do
    result = check(
      &quot;1 + 2 == 3&quot;,
      &quot;1 + 2 + 33 == 6&quot;,
      &quot;adding negative numbers&quot; =&amp;gt; lambda{ -1 + -3 == -4 }
    )
  end
  result
end

def test_times
  result = false
  Dynamic.let :test_name =&amp;gt; &apos;test_times&apos; do
    result = check(
      &quot;2 * 2 == 4&quot;,
      &quot;3 * 5 == 15&quot;
    )
  end
  result
end
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Lastly we just add the dynamic variable to the print statement in report_result:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;def report_result(test)
  if block_given?
    result = yield
  else  
    result = eval(test)
  end
  puts &quot;#{result ? &apos;pass&apos; : &apos;FAIL&apos;} ... #{Dynamic.test_name}: #{test}&quot;
  result
end
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;So now we want to clean up this redundant test code, but alas, Ruby does not have macros.  Here we go again, coming pretty close.  Define a method we will use to define tests:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;def test(name)
  test_name = &quot;test_#{name}&quot;
  method = lambda do
    result = false
    Dynamic.let :test_name =&amp;gt; &quot;#{Dynamic.test_name} #{test_name}&quot; do
      result = yield
    end
    result
  end    
  Object.send(:define_method, test_name, method)
end
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;I&apos;m not even going to try to explain how this code works.  This is pretty dense.  I&apos;m not sure if it is more or less dense than the Lisp code.  Now that we have our Ruby &quot;macro&quot; created, we can define our tests like this:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;test &quot;plus&quot; do
  check(
    &quot;1 + 2 == 3&quot;,
    &quot;1 + 2 + 3 == 6&quot;,
    &quot;adding negative numbers&quot; =&amp;gt; lambda{ -1 + -3 == -4 }
  )
end

test &quot;times&quot; do 
  check(
    &quot;2 * 2 == 4&quot;,
    &quot;3 * 5 == 15&quot;
  )
end

test &quot;arithmetic&quot; do
  %w{test_plus test_times}.each? do |t|
    send t
  end
end

test &quot;math&quot; do
  test_arithmetic
end
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;And voila, we have a feature complete version of the test framework in Ruby:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;irb(main):096:0&amp;gt; test_math
pass ...  test_math test_arithmetic test_plus: 1 + 2 == 3
pass ...  test_math test_arithmetic test_plus: 1 + 2 + 3 == 6
pass ...  test_math test_arithmetic test_plus: adding negative numbers
pass ...  test_math test_arithmetic test_times: 2 * 2 == 4
pass ...  test_math test_arithmetic test_times: 3 * 5 == 15
=&amp;gt; true
irb(main):097:0&amp;gt; test_arithmetic
pass ...  test_arithmetic test_plus: 1 + 2 == 3
pass ...  test_arithmetic test_plus: 1 + 2 + 3 == 6
pass ...  test_arithmetic test_plus: adding negative numbers
pass ...  test_arithmetic test_times: 2 * 2 == 4
pass ...  test_arithmetic test_times: 3 * 5 == 15
=&amp;gt; true
irb(main):098:0&amp;gt; test_plus
pass ...  test_plus: 1 + 2 == 3
pass ...  test_plus: 1 + 2 + 3 == 6
pass ...  test_plus: adding negative numbers
=&amp;gt; true
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;So in conclusion, macros are one feature of Lisp that have no direct equivalent in Ruby, but you can define methods that define methods, which is pretty close to what macros do.  Given Ruby&apos;s metaprogramming features like eval, send, and define_method, etc., Do you really need macros?.  The search for the answer continues...&lt;/p&gt;
</content>
  </entry>
  </feed>