Hi,

> On 24 Nov 2018, at 15:14, Alexandre Rademaker <aradema...@gmail.com> wrote:
> 
> 
> In the LoL book we learn the flexibility of the Common Lisp macro system. 
> Reading now 
> 
> http://blog.racket-lang.org/2011/04/writing-syntax-case-macros.html 
> <http://blog.racket-lang.org/2011/04/writing-syntax-case-macros.html>
> 
> It seems that the Racket macros do not necessarily impose constraints to the 
> programmers. But I never really used it. Does anyone here have experiences 
> with both approaches, sufficient to give insights about the good and bad of 
> each one? 


syntax-case is, strictly speaking, strictly more expressive than Common Lisp 
macros. If it is worth it to switch to syntax-case because of this, is a 
different question though, because you can make an argument that the increase 
in expressiveness doesn’t solve an essential problem.

syntax-case solves a particular case of macro hygiene issues. (syntax-rules 
solves it too, but removes a lot of other possibilities to express things, 
whereas syntax-case doesn’t have such restrictions.)

The problem can be illustrated with a simple example:

(defun foo ()
   (let ((x 42))
      (macrolet ((bar () ‘x))
         (let ((x 4711))
            (bar)))))

It can be argued, especially if you’re a very strong believer that everything 
should be lexically scoped without exception, that (foo) should return 42, 
because the bar macro apparently refers to the variable named x bound to 42. 
Alas, (foo) actually returns 4711, and Common Lisp provides no way to solve 
this /in the language/. (That last part, “in the language”, is very important 
when speaking of expressiveness. There are very good pragmatic solutions to 
this issue which, however, only work by convention and are not based on 
explicit language mechanisms. My favorite solution is to just use different 
names for the different bindings. ;)

With syntax-case and its default notations, which look very different from the 
Common Lisp macro system, (foo) would by default return 42, but there are 
mechanisms in syntax-case to also return 4711 if you explicitly ask for it, 
without renaming any of the variables.

There is a very interesting paper by Daniel Friedman called “Object-Oriented 
Style” - see https://www.cs.indiana.edu/~dfried/ 
<https://www.cs.indiana.edu/~dfried/> - where he implements an object system 
completely in syntax-case (that is, without the need for any particular runtime 
support), and where a variant of this issue pops up. I found it very 
enlightening to try to reimplement this with Common Lisp’s macro system, 
because you can actually get very far with it. (There are some tricks using 
&env-based environment objects, macroexpand with explicit passing of such 
environment objects, and symbol-macrolet, but you will ultimately arrive at a 
stumbling block where this doesn’t work anymore.)

This paper motivated me to actually embed hygienic macros in Common Lisp. This 
is described in 
http://www.jucs.org/jucs_16_2/embedding_hygiene_compatible_macros 
<http://www.jucs.org/jucs_16_2/embedding_hygiene_compatible_macros>

However, this is not a solution “in the language” because this only works 
reliably if you write your whole programs in that system.

I’m still not convinced that hygienic macro systems like syntax-case are worth 
the complexity. Again, just don’t reuse variable names, and you should be fine. 
(For global variables, it’s easy to use the Common Lisp package system to solve 
hygiene issues.)

Just my 0.02€.


Pascal

--
Pascal Costanza


Reply via email to