In a previous thread Charles Oliver Nutter had suggested the removal
of Proc#binding.  In response I showed my workaround for the lack of
keyword arguments in Ruby:

def f(opts)
  a, b, c = nil
  hash_to_locals { opts }
  p [a, b, c]
end

f(:a => 33, :b => 44, :c => 55)  #=> [33, 44, 55]

Charles said this is scary--that it should be written: hash_to_locals
opts, binding.

I later realized that I was being scary on purpose.  locals_to_hash is
not intended to be understood as a normal function.  I am trying to
squeeze out some macro-like behavior from Ruby.

How many times have you seen code like this:

database << {
  :address => address,
  :city => city,
  :phone => phone,
  :email => email,
  :number_of_digits => number_of_digits,
}

A macro could fix the redundancy, but using (or abusing) the proc
binding gets us halfway there,

database << locals_to_hash {%{address city phone email number_of_digits}}

If locals_to_hash needed a second binding parameter, this expression
would require parentheses and incidentally push it to two lines.  That
would not be so bad, it's just a slightly more concussive head-bonking
against the ceiling of possible abstractions in Ruby.

The abuse of Proc#binding is a symptom of something.  Whether
knowingly or not, people use it to simulate macros.  If Ruby supported
some kind of macro behavior, there would be no need for Proc#binding.
I could write a clean locals_to_hash without {%{}}, and the door would
be open for the optimizations sought by our preeminent jruby
developer.

Another example: in order to send functions over the wire, a lambda
definition must be given as a string (ParseTree is for MRI-1.8 only).
This is very awkward.  The practical outcome is that a given Rakefile
cannot be parallelized across machines.  The choices are (1) replace
the nice DSL-like Rakefile syntax with something hideous, (2) retain
the current Rakefile format by using macros, or (3) give up on the
possibility of distributed builds based on a simple Rakefile.

Given a Ruby with macros, proposals such as the current one for
selector namespaces could be implemented without changes to the
language.  If people could experiment with competing implementations
written in pure Ruby, the final outcome (if any) would likely be
better.

I don't know how seriously people will consider the idea of macros in
Ruby.  I would only suggest that it shouldn't be dismissed outright.
The following is my loosely held opinion on the matter.

Ruby syntax should not be mutable, only the generated meaning after
the initial parse--which should also be valid Ruby syntax.  This would
be in contrast to Perl 6, which from my understanding allows the
creation of new syntax.

I do not believe an implementation should expose its AST.  Even in
Common Lisp an implementation is free to ignore
function-lambda-expression.

Instead, macro transforms could be done with strings, allowing
implementations free reign to change their ASTs on a whim.  It is much
easier (and more rubyish) to generate strings than to wade through
s-exp data.  The author of ruby-rewrite says, "writing new features is
torturous."  And it is, if you must juggle s-exps.  For more complex
transforms, an implementation-neutral s-exp format could be generated
like the one used by ruby_parser.   But for most cases simple string
generation is sufficient.

After looking at a few ruby_parser examples, in just 40 lines of code
I was able to write a transformer which allowed me to define the
seamless locals_to_hash I wanted.  This runs on 1.8, 1.9, and jruby --
anything which runs ruby_parser (and limited to syntax supported by
ruby_parser).

% ./macroruby locals_to_hash.rb
------------------------------------------------------------
* original code:

def macro_locals_to_hash(receiver, *args)
  args.inject("{") { |acc, arg|
    acc << ":#{arg}=>#{arg},"
  } << "}"
end

a = 33
b = 44
h = locals_to_hash(a, b)
p h  # => { :a => 33, :b => 44 }
------------------------------------------------------------
* transformed code:
# do nothing
a = 33
b = 44
h = { :a => (a), :b => (b) }
p(h)
------------------------------------------------------------
* run:
{:a=>33, :b=>44}

http://github.com/quix/macroruby/tree/master