From: Spiros Bousbouras on
On 17 Nov, 18:01, "Tobias C. Rittweiler" <t...(a)freebits.de.invalid>
wrote:
> Spiros Bousbouras <spi...(a)gmail.com> writes:
>
> > In my code above nothing is leaking but my code doesn't do what I
> > want. In the solutions posted by the two Pascals a symbol-macro cell
> > is introduced in the global environment. That's what's leaking. In
> > Pascal B.'s solution also the dynamic variable *cell* is leaking.
>
> Pascal Costanza's example contained a global symbol macro, though you
> don't need it.

How can you do the same thing without a global symbol macro ?

> Are internally used functions to implement other functions also an
> example of leaking? Or variables? They all introduce stuff into the
> global environment. What's the difference?

What do you mean "internally" ? Show me some code and I'll tell you.

> > The ability to expand macros is a good thing. As I said in my opening
> > post , if Lisp had a minimal-compile function (which in a sense would
> > be a stronger version of macroexpand) , I could do what I want in a
> > clean and more elegant manner. Actually I find it surprising that it
> > doesn't. minimal-compile would be more or less something which does
> > more than macroexpand but less than eval.
>
> It's commonly called MACROEXPAND-ALL.

Brilliant. I will return to this, probably in a different thread.

> > And the issues here are elegance , practicality and even speed of
> > compilation.
>
> How does MACROEXPAND-ALL help the speed of compilation?

I'm not sure that it will but I thought that if it makes the
implementation of certain macros simpler or the expanded code smaller
then this might help the speed of compilation.

> Using it, the
> implementation has to walk the syntax tree twice.

Yes but the second time it won't have to expand any macros. So on one
hand it might make the macroexpansion function or the expanded code
of some macros smaller but on the other it will have to parse some
stuff twice. I was thinking that in some cases the first may outweigh
the second.

> Do you know that it can in fact lead to an _impairment_ of runtime speed
> because implementation which would previously implement some macros as
> special forms cannot do so?

No I didn't know it. Can you give me an example of something an
implementation can do without MACROEXPAND-ALL that it couldn't do if
MACROEXPAND-ALL existed ?

--
But, to wring a new twist on an old phrase, power corrupts. And
Mississippi Burning is corrupted by the reckless exhilaration it
betrays in wielding its own pumped-up, self-inflated cinematic power.
http://cinepad.com/reviews/mississippi.htm
From: Spiros Bousbouras on
On 17 Nov, 20:15, Pascal Costanza <p...(a)p-cos.net> wrote:
> Spiros Bousbouras wrote:
> > On 11 Nov, 00:40, Pascal Costanza <p...(a)p-cos.net> wrote:
> >> Spiros Bousbouras wrote:
>
> >>> (let ((a 0))
> >>> (defmacro memory (&rest body)
> >>> (prog2
> >>> (incf a)
> >>> `(symbol-macrolet ((cell ,a))
> >>> ,@body)
> >>> (decf a))))

[...]

> > Is there any established way for how such parallel
> > expansion/compilation is supposed to work ? Intuitively it seems to
> > me that in the scenario you're describing the implementation ought to
> > create one copy of a for the compilation and another for any
> > expansions which are not part of the compilation. If it doesn't do
> > that what makes you think that even your code will work correctly ?
> > There may be clashes with the use of new-cell-value.
>
> Huh? new-cell-value is lexically bound, so it's guaranteed to have its
> own binding per invocation.

Guaranteed by what ? This situation is not covered by the standard ,
is it ? In any case in my code the variable a is also lexically
bound.

--
Who's your mama ?
From: Pascal Costanza on
Spiros Bousbouras wrote:
> On 17 Nov, 20:15, Pascal Costanza <p...(a)p-cos.net> wrote:
>> Spiros Bousbouras wrote:
>>> On 11 Nov, 00:40, Pascal Costanza <p...(a)p-cos.net> wrote:
>>>> Spiros Bousbouras wrote:
>>>>> (let ((a 0))
>>>>> (defmacro memory (&rest body)
>>>>> (prog2
>>>>> (incf a)
>>>>> `(symbol-macrolet ((cell ,a))
>>>>> ,@body)
>>>>> (decf a))))
>
> [...]
>
>>> Is there any established way for how such parallel
>>> expansion/compilation is supposed to work ? Intuitively it seems to
>>> me that in the scenario you're describing the implementation ought to
>>> create one copy of a for the compilation and another for any
>>> expansions which are not part of the compilation. If it doesn't do
>>> that what makes you think that even your code will work correctly ?
>>> There may be clashes with the use of new-cell-value.
>> Huh? new-cell-value is lexically bound, so it's guaranteed to have its
>> own binding per invocation.
>
> Guaranteed by what ? This situation is not covered by the standard ,
> is it ?

Lexical bindings? Of course they are covered by the standard.

> In any case in my code the variable a is also lexically bound.

But you're performing side effects on this lexically bound variable,
which may lead to race conditions when multiple threads expand this one
macro. This is then a situation of concurrent write accesses to shared
memory, which usually need to be synchronized. In a 'pure binding'
(purely functional) situation, you don't have these problems.

Yes, _multithreading_ is not covered by the standard, but there are
numerous multithreaded Common Lisp implementations, so if you want your
code to be portable, you better take that into account.


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: Tobias C. Rittweiler on
Spiros Bousbouras <spibou(a)gmail.com> writes:

> On 17 Nov, 18:01, "Tobias C. Rittweiler" wrote:
>
> > Spiros Bousbouras <spi...(a)gmail.com> writes:
> >
> > > In my code above nothing is leaking but my code doesn't do what I
> > > want. In the solutions posted by the two Pascals a symbol-macro cell
> > > is introduced in the global environment. That's what's leaking. In
> > > Pascal B.'s solution also the dynamic variable *cell* is leaking.
> >
> > Pascal Costanza's example contained a global symbol macro, though you
> > don't need it.
>
> How can you do the same thing without a global symbol macro ?

(defmacro memory (&body body &environment env)
(multiple-value-bind (old-cell-value expandedp)
(macroexpand 'cell env)
`(symbol-macrolet ((cell ,(1+ (if expandedp old-cell-value 0))))
,@body)))


> > Are internally used functions to implement other functions also an
> > example of leaking? Or variables? They all introduce stuff into the
> > global environment. What's the difference?
>
> What do you mean "internally" ? Show me some code and I'll tell you.

(defpackage :foof (:use :cl) (:export #:frobf))
(in-package :foof)
(defun internal-fn (x) (* x x)
(defun frobf (x y) (+ (internal-fn x) y))

A function (INTERNAL-FN) is introduced in the global environment solely
to implement the behaviour of FROBF. In your definition quoted above,
it's leaking something.


> > Do you know that it can in fact lead to an _impairment_ of runtime speed
> > because implementation which would previously implement some macros as
> > special forms cannot do so?
>
> No I didn't know it. Can you give me an example of something an
> implementation can do without MACROEXPAND-ALL that it couldn't do if
> MACROEXPAND-ALL existed ?

Say your implementation implements DOLIST as a special form[*] for
reasons of efficiency. In case of

(defun foo (list &aux (sum 0)) (dolist (i list sum) (incf sum i)))

the implementation can process DOLIST as a special form.

Contrarily on:

(defmacro walk-at-compile-time (form &environment env)
(macroexpand-all form env))

(defun bar (list &aux (sum 0))
(walk-at-compile-time (dolist (i list sum) (incf sum i))))

the implementation has to expand the DOLIST form into something probably
involving TAGBODY. We assumed that the implementation as special form
would be more efficient -- so this shows how code-walking can impose
runtime penalty.

-T.


[*] This is not just an academic point. For example, ABCL's interpreter
implements DOLIST etc. as special form because it can then execute the
loop directly in Java instead of having to interpret a Lisp loop.
From: Spiros Bousbouras on
On 17 Nov, 14:48, Pillsy <pillsb...(a)gmail.com> wrote:
> On Nov 10, 4:36 pm, Spiros Bousbouras <spi...(a)gmail.com> wrote:
> [...]
>
> > In any case, it seems that if one wants to have macros share
> > information (apart from trivial cases perhaps) then this cannot be
> > achieved behind the scenes so to speak. What I mean behind the scenes
> > is the way you would do it with functions:
> > (let ((a))
> > (defun foo ...
> > (defun bar ...)
> > Any changes to a one function makes the other knows about but the
> > rest of the code is ignorant about a.
>
> This is a trick I've used once or twice in the past, and I'm just
> submitting it as an idea in part because I'd like to see if there are
> problems with it that I haven't considered up until now. It's hardly
> something I do every day, and I know this corner of macrology is
> generally riddled with pitfalls.
>
> The idea is that you have easy access to uninterned symbols, and those
> symbols not only have their value cells, but also function cells and
> property lists to play with. You could do something like this:
>
> (let ((closed (closed "BACKING-")))

Is the second "closed" meant to be "gensym" ?

> (defmacro foo (name &rest args)
> (setf (get closed name) (stuff-from-foo-args args))
> (generate-foo-expansion name args closed))
> (defmacro bar (name &rest args)
> (setf (get closed name) (stuff-from-bar-args args))
> (generate-bar-expansion name args closed)))
>
> Is there something horribly wrong with this approach?

I'm afraid I don't understand what the various ingredients like
closed , name , stuff-from-foo-args are supposed to do. Could you
post some specific example which uses your technique ?

Nevertheless your code gave me the idea for the following approach:

(let ((a (gensym "memory-var-")))
(defmacro memory (&body body)
`(progn
(if (boundp ',a)
(incf ,a)
(defvar ,a 1))
(symbol-macrolet ((cell ,a))
(prog1
,@body
(decf ,a))))))

It solves the problem of "reserving" for itself a name for a global
symbol. And yes , I know it uses side effects but I'm not convinced
this is something worrying about.

--
Who's your mama ?
First  |  Prev  |  Next  |  Last
Pages: 1 2 3 4 5 6 7 8
Prev: Lisp sucks!
Next: grabbing key presses