Hacker News new | past | comments | ask | show | jobs | submit login

In the "Macro Basics" section, he seems to completely glaze over the _other_ problem with unhygenic macros.[1]

Consider:

  (defmacro square (x)
    `(* ,x ,x))

  (let ((* my-vector-dot-product))
    ...
    (square (* bar baz)))
He seems a bit brash in his attacks on Scheme and insistence that hygenic macros are bad. He doesn't even mention Clinger's explicit renaming macros which solve the problem without using a DSL (an approach which he derides).

Also, what about side effecting arguments to macros? I'm hesitant to put too much credence in this book when it seems to ignore significant problems with defmacro.

[1] http://letoverlambda.com/index.cl/guest/chap3.html#sec_5




There are two problems with your example. First is that Common Lisp is a lisp-2 so the '*' function won't actually be rebound at all.

Secondarily, and more importantly, every unhygienic lisp I've used has had a broader namespacing system which takes care of this. The compiler warns you whenever you are about to rebind something within the same namespace.


Like, Common Lisp? (Clozure)

    ? (defun plus (&rest x) (apply #'+ x))
    PLUS
    ? (defmacro mplus (&rest x) `(plus ,@x))
    MPLUS
    ? (flet ((plus (&rest x) (apply #'* x))) (mplus 4 9))
    36 ;; Uh oh, looks like my function was rebound
    ? (plus 4 9)
    13
How about functions in the CL package?

    ? (defmacro mplus (x y) `(+ ,x ,y))
    MPLUS
    ? (flet ((+ (x y) (- x y))) (mplus 8 4))
    4


Your second example throws an error for me. (SBCL)

The first doesn't (it appears flet doesn't trigger the error in this situation) but the package system still mitigates the damage in practice. I've written a lot of macros and haven't yet accidentally rebound a special function with flet which a macro relied upon.


> Your second example throws an error for me. (SBCL)

According to the CL standard, you shouldn't be able to redefine or shadow special operators, functions, or macros in the COMMON-LISP package. SBCL does the right thing by the spec, but it's really a weakness of the spec that makes CL less general than it can be.

This restriction and the multiple namespaces of Common Lisp (and given appropriate use of gensym) is why almost all of the time CL macros work without need of hygiene. But there's nothing stopping surprises when you call functions or macros defined in packages other than COMMON-LISP.




Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: