From: Helmut Eller on
* Pascal Costanza [2010-03-25 11:50+0100] writes:

> On 25/03/2010 07:51, Kazimir Majorinc wrote:
>> Do CL-ers agree with Eli?
>
> What Eli says is correct, but only relevant when you use local macro
> definitions. A canonical example is this:
>
> (let ((x 1))
> (macrolet ((foo () 'x))
> (let ((x 2))
> (foo))))
>
> You have two variable bindings for x, and the expansion of foo will
> refer to the inner one, so this form will yield 2. If you want to keep
> the name x for both variable bindings, there is no way in Common Lisp
> to reliably rewrite the macro foo such that it unambiguously refers to
> the outer x, without adding some serious heavy machinery on top of
> Common Lisp.

You could simply write it as:

(let ((x 1))
(flet ((foo () x))
(let ((x 2))
(foo))))

Or if you insist on using macros:

(defmacro macrolet-with-alias ((macro-name (alias name) args
&body expander)
&body body)
(let ((sym (gensym)))
`(flet ((,sym () ,name))
(macrolet ((,macro-name ,args
(symbol-macrolet ((,alias '(,sym)))
. ,expander)))
. ,body))))

(defun foo ()
(let ((x 1))
(macrolet-with-alias (foo (alias x) ()
`,alias)
(let ((x 2))
(foo)))))

Helmut
From: Pascal Costanza on
On 25/03/2010 15:11, Kazimir Majorinc wrote:
> On 25.3.2010 11:50, Pascal Costanza wrote:
>
>> Of course, you could decide to rename one of the two variable bindings.
>
> OK. But isn't it possible to change macrolet definition:
>
> (let((x 1))
> (macrolet-with-gensyms ((foo () 'x))
> '(x); 'variables to be replaced with gensyms
> (let ((x 2))
> (foo))))
>
> == expands to ==>
>
> (let((x 1))
> (let ((G3197 x))
> (macrolet((foo () 'G3197))
> (first (list (let ((x 2))
> (foo))))
> (setf x G3197)))) ;==>1
>
> With real gensyms, these are manual equivalents.
> Both outer and inner bindings are here,
> which part of the problem is left?

(let ((x 1))
(macrolet ((foo () 'x))
(let ((x 2))
(incf (foo)))))


Pascal

--
My website: http://p-cos.net
Common Lisp Document Repository: http://cdr.eurolisp.org
Closer to MOP & ContextL: http://common-lisp.net/project/closer/
From: Pascal Costanza on
On 25/03/2010 15:21, Helmut Eller wrote:
> * Pascal Costanza [2010-03-25 11:50+0100] writes:
>
>> On 25/03/2010 07:51, Kazimir Majorinc wrote:
>>> Do CL-ers agree with Eli?
>>
>> What Eli says is correct, but only relevant when you use local macro
>> definitions. A canonical example is this:
>>
>> (let ((x 1))
>> (macrolet ((foo () 'x))
>> (let ((x 2))
>> (foo))))
>>
>> You have two variable bindings for x, and the expansion of foo will
>> refer to the inner one, so this form will yield 2. If you want to keep
>> the name x for both variable bindings, there is no way in Common Lisp
>> to reliably rewrite the macro foo such that it unambiguously refers to
>> the outer x, without adding some serious heavy machinery on top of
>> Common Lisp.
>
> You could simply write it as:
>
> (let ((x 1))
> (flet ((foo () x))
> (let ((x 2))
> (foo))))

(let ((x 1))
(flet ((foo () x))
(let ((x 2))
(incf (foo))))) => doesn't work


Pascal

--
My website: http://p-cos.net
Common Lisp Document Repository: http://cdr.eurolisp.org
Closer to MOP & ContextL: http://common-lisp.net/project/closer/
From: Helmut Eller on
* Pascal Costanza [2010-03-25 16:14+0100] writes:

> On 25/03/2010 15:21, Helmut Eller wrote:
>> * Pascal Costanza [2010-03-25 11:50+0100] writes:
>>
>>> On 25/03/2010 07:51, Kazimir Majorinc wrote:
>>>> Do CL-ers agree with Eli?
>>>
>>> What Eli says is correct, but only relevant when you use local macro
>>> definitions. A canonical example is this:
>>>
>>> (let ((x 1))
>>> (macrolet ((foo () 'x))
>>> (let ((x 2))
>>> (foo))))
>>>
>>> You have two variable bindings for x, and the expansion of foo will
>>> refer to the inner one, so this form will yield 2. If you want to keep
>>> the name x for both variable bindings, there is no way in Common Lisp
>>> to reliably rewrite the macro foo such that it unambiguously refers to
>>> the outer x, without adding some serious heavy machinery on top of
>>> Common Lisp.
>>
>> You could simply write it as:
>>
>> (let ((x 1))
>> (flet ((foo () x))
>> (let ((x 2))
>> (foo))))
>
> (let ((x 1))
> (flet ((foo () x))
> (let ((x 2))
> (incf (foo))))) => doesn't work

(defun foo ()
(let ((x 1))
(flet ((foo () x)
((setf foo) (value) (setf x value)))
(let ((x 3))
(incf (foo))))))

Does work

Helmut
From: Pascal Costanza on
On 25/03/2010 16:35, Helmut Eller wrote:
> * Pascal Costanza [2010-03-25 16:14+0100] writes:
>
>> On 25/03/2010 15:21, Helmut Eller wrote:
>>> * Pascal Costanza [2010-03-25 11:50+0100] writes:
>>>
>>>> On 25/03/2010 07:51, Kazimir Majorinc wrote:
>>>>> Do CL-ers agree with Eli?
>>>>
>>>> What Eli says is correct, but only relevant when you use local macro
>>>> definitions. A canonical example is this:
>>>>
>>>> (let ((x 1))
>>>> (macrolet ((foo () 'x))
>>>> (let ((x 2))
>>>> (foo))))
>>>>
>>>> You have two variable bindings for x, and the expansion of foo will
>>>> refer to the inner one, so this form will yield 2. If you want to keep
>>>> the name x for both variable bindings, there is no way in Common Lisp
>>>> to reliably rewrite the macro foo such that it unambiguously refers to
>>>> the outer x, without adding some serious heavy machinery on top of
>>>> Common Lisp.
>>>
>>> You could simply write it as:
>>>
>>> (let ((x 1))
>>> (flet ((foo () x))
>>> (let ((x 2))
>>> (foo))))
>>
>> (let ((x 1))
>> (flet ((foo () x))
>> (let ((x 2))
>> (incf (foo))))) => doesn't work
>
> (defun foo ()
> (let ((x 1))
> (flet ((foo () x)
> ((setf foo) (value) (setf x value)))
> (let ((x 3))
> (incf (foo))))))

Yes, and you're adding more and more definitions. If on top of that, you
actually want a _macro_, you still haven't solved the problem (without
adding more heavy machinery).

Yes, you can always find workarounds for concrete examples (after all,
you're in control of the complete expression), but there is no general
solution that works the same for all cases, unless you introduce one of
the known ways to make macro definition hygienic.

(I'm not trying to say that Common Lisp has a serious problem here. To
the contrary, I think the trade off made in Common Lisp's macro system
is the right one - adding more features to guarantee macro hygiene makes
a macro system more complicated than necessary, for no real benefit, and
the known workarounds are, IMO, good enough. But that doesn't change the
fact that Common Lisp's macro system does not provide straightforward
means to write hygienic macros, and the only thing I'm doing here is to
acknowledge that.)


Pascal

--
My website: http://p-cos.net
Common Lisp Document Repository: http://cdr.eurolisp.org
Closer to MOP & ContextL: http://common-lisp.net/project/closer/