This post originated from an RSS feed registered with Ruby Buzz
by Jay Fields.
Original Post: Macros Facilitate Expressive Code
Feed Title: Jay Fields Thoughts
Feed URL: http://blog.jayfields.com/rss.xml
Feed Description: Thoughts on Software Development
Someone once asked me if I thought Clojure was more expressive than even Ruby. I didn't have enough information to form an opinion then, and I still don't now. However, I recently noticed something that led me to believe the answer could actually be yes.
I was looking through the code of clojure.test on Friday and I noticed something interesting. In clojure.test, the form(s) passed to the "is" macro are wrapped by a try/catch. It caught my eye because I often want to do the same thing in other languages, and usually I have to settle for much less elegant solutions.
Here's a bit of example code to help create some context
For this example to work you'll have to ignore the fact that you probably don't want this behavior. In practice I prefer my tests to abort on the first failing assertion; however, in this blog entry I'm focusing on what's happening, not what I theoretically prefer.
In the example I call a function the same way I would anywhere else, and the framework has full control over what happens if my function throws an exception. This is accomplished when the "is" macro takes the forms and manipulates them into something similar to the original code, but with additional capabilities.
This particular example struck me as one where Macros allow you to write only what you want, and the macro can adds the additional behavior that you desire. However, the key is, you don't have to do anything special to get this additional behavior.
Consider trying to do the same thing in Ruby. In Test::Unit you would need an assert method that took a block.
defsafe_assert_equal result =yield assert_equal result.first, result.last rescueException=>e puts e end
classTestable< Test::Unit::TestCase deftest_something safe_assert_equal {[1,2]} end end
The additional syntax isn't drastically invasive; however, you are forcing additional syntax and requiring the understanding of why it's necessary.
Of course, in Java things would be even less expressive. The most likely solution would be to put the assertEquals in a Runnable, but I'd be interested in hearing other ideas. Regardless of the solution, it would obviously be invasive and take away from the readability of the test.
Being able to only say what is necessary is powerful. Stuart Halloway likes to talk about Essence and Ceremony, where Essence is the ability to say only what you want, and Ceremony is all the additional things you are required to say.
Macros seem to be a powerful tool for those looking to write Ceremony-free code.