[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: macros vs. blocks

John Clements <clements@brinckerhoff.org> writes:

> Hmm.  If you consider the three largest categories of macros [*] to be
> 1) those that affect evaluation order (if),
> 2) those that introduce literal data (quote), and
> 3) those that introduce bindings (let),
> I don't see how block notation solves any other than category (1).

I would refine my macros-are-useless claim a bit: languages that already
have syntax for things such as assignment, variable declaration, and
quoted data (Python, Perl, Smalltalk, ...) don't benefit much from

Using macros for #2 is probably a bad idea. I think it's generally
clearer to include the ' symbol (or whatever your favorite language
uses) than to have some arguments be magically quoted.

Using macros for #3 is also usually a bad idea. Having macros like CL
(do) or (while), which magically introduce a variable with non-obvious
scoping, is hazardous. I'd rather just have one way of declaring
control-structure variables, like Smalltalk:

  list do: [:x |
      x print.

where it's totally obvious what the scope of the variable is. Scheme
succeeds here too, because it uses lambda semantics everywhere.

Alan Bawden <Alan@LCS.MIT.EDU> writes:

>  (define-syntax assert
>    (syntax-rules ()
>      ((assert test)
>       (if (not test) (assert-error (quote test))))))

The assert family is certainly a classic macro application, although
having it print something like


is pretty darn useless, since there might be lots of occurrences of
(assert (> x 0)) in the code, and also that assertion failures often
indicate an error in the caller rather than where the assert statement
is. I'd much rather rely on the stack traceback with line numbers and 
function arguments that any good interpreted language gives you. So I
claim this sort of pun is pretty useless.

Guy Steele <Guy.Steele@Sun.COM> writes:

> (defmacro findroots (lx)

While this sort of destructuring of code is a fabulous hack, I don't
believe it's all that useful in practice. For one, if you have an OO
sort of number system, you can usually define a newton-variable type,
with its own implementation of the standard arithmetic operators to
generate a parse tree rather than a numerical result. That ends up being
more flexible and probably easier to write. Avi Bryant <avi@beta4.com> 
made a similar point in the context of database query languages.

Scott McKay <swm@itasoftware.com> writes:

> ;; Defines the (empty) element <hd:image-server/>
> (define-element image-server ()
>   (show-string *image-server-url*))

These sort of function-plus-linkage definitions are a reasonable use of
macros. But, having to write something like:

(defun image-server ...)
(register-tag 'image-server image-server)

really isn't that bad. Especially since you often want several different
tags to share code, or you often want to add a bunch of similar tags:

(dolist color '(red green blue)
  (register-tag color (lambda () (format t "<font color=~A>" color))))

DLWeinreb@attbi.com writes:

> [...] optimizations [...]

I'm also ignoring any speedup from compile-time processing of macro
arguments. I basically don't believe in language features for speed
tuning, other than allowing you to write your most critical bit-fiddling
inner loops at the level of C.

Trevor Blackwell      tlb@anybots.com       (650) 776-7870