Ruby metaprogramming with s-expressions

Metaprogramming is code writing code. Usually metaprogramming in Ruby is done using the reflection features of the language: define_method, instance_variable_get, and others. In this post you will see another way to do metaprogramming that has some advantages over the traditional approach.

An example of metaprogramming in Ruby is attr_reader, which defines a reader for an instance variable. In the following class attr_reader defines readers for @x and @y:

class XY
attr_reader :x, :y
end

That code is functionally equivalent to this code, which defines readers explicitly:

class XY
def x
return @x
end
def y
return @y
end
end

You could* implement attr_reader in Ruby using define_method and instance_variable_get:* but don’t do that! Ruby interpreters optimize attr_reader as a special case.

class Module
def attr_reader(*names)
names.each do |name|
iv_name = "@#{name}"
define_method(name) do
instance_variable_get(iv_name)
end
end
return
end
end

This is the traditional approach to metaprogramming in Ruby: using the reflection features of the language, which take effect when the interpeter executes the program.

But another way to do metaprogramming is to generate Ruby source code, using the meta-ruby gem. The meta-ruby gem generates Ruby source code from s-expressions. The generated code can be written to a file to be read by a Ruby interpreter.