Take the 2-minute tour ×
Programmers Stack Exchange is a question and answer site for professional programmers interested in conceptual questions about software development. It's 100% free, no registration required.

Common Lisp allows you to write macros that do whatever source transformation you want.

Scheme gives you a hygienic pattern-matching system that lets you perform transformations as well. How useful are macros in practice? Paul Graham said in Beating the Averages that:

The source code of the Viaweb editor was probably about 20-25% macros.

What sorts of things do people actually end up doing with macros?

share|improve this question
    
I think this definitely falls into good subjective, I've edited your question for formatting. This could be a duplicate, but I could not find one. –  Tim Post Dec 13 '11 at 21:36
1  
Everything repetive that doesn't appear to fit into a function, I'd guess. –  delnan Dec 13 '11 at 21:42
2  
You can use macros to turn Lisp into any other language, with any syntax and any semantics: bit.ly/vqqvHU –  SK-logic Dec 13 '11 at 23:32
    
programmers.stackexchange.com/questions/81202/… is worth looking at here, but it isn't a duplicate. –  David Thornley Dec 14 '11 at 22:16
add comment

5 Answers

up vote 7 down vote accepted

Take a look at this posting by Matthias Felleisen to the LL1 discuss list in 2002. He suggests three main uses for macros:

  1. Data sublanguages: I can write simple-looking expressions and create complex nested lists/arrays/tables with quote, unquote, etc. neatly dressed up with macros.
  2. Binding constructs: I can introduce new binding constructs with macros. That helps me get rid of lambdas and place things closer together that belong together.
  3. Evaluation reordering: I can introduce constructs that delay/postpone the evaluation of expressions as needed. Think of loops, new conditionals, delay/force, etc. [Note: In Haskell or any lazy language, this one is unnecessary.]
share|improve this answer
add comment

I mostly use macros for adding time-saving new language constructs, that would otherwise require a bunch of boilerplate code.

For example, I recently found myself wanting an imperative for-loop similar to C++/Java. However, being a functional language, Clojure didn't come with one out of the box. So I just implemented it as a macro:

(defmacro for-loop [[sym init check change :as params] & steps]
  `(loop [~sym ~init value# nil]
     (if ~check
       (let [new-value# (do ~@steps)]
         (recur ~change new-value#))
       value#)))

And now I can do:

 (for-loop [i 0 , (< i 10) , (inc i)] 
   (println i))

And there you have it - a new general-purpose compile-time language construct in six lines of code.

share|improve this answer
add comment

Macros are useful to embedded some patterns.

For example, Common Lisp doesn't define the while loop but has do which can be used to define it.

Here is an example from On Lisp.

(defmacro while (test &body body)
  `(do ()
       ((not ,test))
     ,@body))

(let ((a 0))
  (while (< a 10)
    (princ (incf a))))

This will print "12345678910", and if you try to see what happens with macroexpand-1:

(macroexpand-1 '(while (< a 10) (princ (incf a))))

This will return:

(DO () ((NOT (< A 10))) (PRINC (INCF A)))

This is a simple macro, but as said before, they're usually used to define new languages or DSLs, but from this simple example you can already try to imagine what you can do with them.

The loop macro is a good example of what macros can do.

(loop for i from 0 to 10
      if (and (= (mod i 2) 0) i)
        collect it)
=> (0 2 4 6 8 10)
(loop for i downfrom 10 to 0
      with a = 2
      collect (* a i))
=> (20 18 16 14 12 10 8 6 4 2 0)               

Common Lisp has another kind of macros called reader macro which can be used to modify how the reader interprets the code, i.e. you can use them to use #{ and #} has delimiters like #( and #).

share|improve this answer
add comment

Here are some examples:

Scheme:

  • define for function definitions. Basically it makes a shorter way to define a function.
  • let for creating lexically scoped variables.

Clojure:

  • defn, according to its docs:

    Same as (def name (fn [params* ] exprs*)) or (def name (fn ([params* ] exprs*)+)) with any doc-string or attrs added to the var metadata

  • for: list comprehensions
  • defmacro: ironic?
  • defmethod, defmulti: working with multi-methods
  • ns

A lot of these macros make it much easier to write code at a more abstract level. I think of macros as being similar, in many ways, to syntax in non-Lisps.

The plotting library Incanter provides macros for some complex data manipulations.

share|improve this answer
add comment

What sorts of things do people actually end up doing with macros?

Writing language extensions or DSL's.

To get a feel for this in Lisp-like languages, study Racket, which has several language variants: Typed Racket, R6RS, and Datalog.

See also the Boo language, which gives you access to the compiler pipeline for the specific purpose of creating Domain-Specific Languages through macros.

share|improve this answer
add comment

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.