On Nov 23, 2013, at 5:46 AM, Matthias Felleisen wrote:
>> - abstracting over things that are not expressions.
>> 
>> For instance:
>> 
>> cmp_impl!(impl Eq, eq, ne)
>> cmp_impl!(impl TotalEq, equals)
>> cmp_impl!(impl Ord, lt, gt, le, ge)
>> cmp_impl!(impl TotalOrd, cmp -> cmp::Ordering)
>> 
>> Each of these expands into a top-level "impl" declaration, extending 
>> implementations of, e.g., Ord, from type T to type Ratio<T>. 
> 
> 
> Like someone else said, I would classify this kind of macro as a 'binding 
> form' macro assuming you're using 'declaration' in the standard sense. 

Hmm... well, they're not binding any new identifiers; they're just declaring 
that this type implements this trait.  

Moreover, I think there's a clear distinction between motivations:

1) 'let' can't be a function call because function calls can't bind new 
identifiers in the environment of the caller.
2) Rust's 'impl' -- and many other forms in that language -- can't be 
abstracted over because they're not in expression positions; this is the same 
thing that prevents you from abstracting over "define-struct", except with a 
macro.  Indeed, I can't even abstract over function definitions at the top 
level of a module.

The "less enlightened" a language is, the more such non-expression-position 
program fragments there are, and the more valuable macros become.

Moreover -- and this is true in Racket as well -- there's often a deliberate 
rationale at work here; the designers want certain things to be apparent at 
compile time, so that the compiler can do a better job. When these decisions 
get baked into the syntax, then macros become the only way to abstract over 
them.

John


____________________
  Racket Users list:
  http://lists.racket-lang.org/users

Reply via email to