From: Tim Bradshaw
Subject: global lexicals
Date: 
Message-ID: <ey3llxstggd.fsf@tfeb.org>
Following the recent thread about this, I put up a cleaned up toy
thing that I wrote a while ago which does (or is meant to do) global
lexicals using the symbol-macro trick.
http://www.tfeb.org/lisp/toys.html#GLEX

--tim

From: Nils Goesche
Subject: Re: global lexicals
Date: 
Message-ID: <lyade88bke.fsf@cartan.de>
Tim Bradshaw <···@tfeb.org> writes:

> Following the recent thread about this, I put up a cleaned up toy
> thing that I wrote a while ago which does (or is meant to do) global
> lexicals using the symbol-macro trick.
> http://www.tfeb.org/lisp/toys.html#GLEX

Why do you use a hash table?  Isn't something like

(defmacro defglex (var &optional value)
  (let ((gs (gensym (symbol-name var))))
    `(eval-when (:compile-toplevel :load-toplevel :execute)
       (progn
         (declaim (cons ,gs))
         (defvar ,gs (list ,value))
         (define-symbol-macro ,var (car ,gs))))))

good enough (and faster)?

Regards,
-- 
Nils G�sche
"Don't ask for whom the <CTRL-G> tolls."

PGP key ID 0x0655CFA0
From: Tim Bradshaw
Subject: Re: global lexicals
Date: 
Message-ID: <ey38ytstcey.fsf@cley.com>
* Nils Goesche wrote:
> Why do you use a hash table?

I don't want a secret special variable per global lexical, I guess.
No real reason though.  I wasn't worried about performance (it's in
the `some small hacks of no real use' section!).

--tim
From: Rob Warnock
Subject: Re: global lexicals
Date: 
Message-ID: <hYOcned8dZmMQiyjXTWc-g@speakeasy.net>
Tim Bradshaw  <···@cley.com> wrote:
+---------------
| * Nils Goesche wrote:
| > Why do you use a hash table?
| 
| I don't want a secret special variable per global lexical, I guess.
| No real reason though.  I wasn't worried about performance (it's in
| the `some small hacks of no real use' section!).
+---------------

When I did my own version of "deflex" (not shown here: ugly, buggy),
like Tim I didn't want a "secret special variable per global lexical"
either, but instead of a hash table I used an adjustable array so that
each resulting symbol macro expands into:

	(aref *global-lexical-vars* <some-literal-constant-fixnum>)

which should be performant enough, yes?


-Rob

-----
Rob Warnock, PP-ASEL-IA		<····@rpw3.org>
627 26th Avenue			<URL:http://rpw3.org/>
San Mateo, CA 94403		(650)572-2607
From: Tim Bradshaw
Subject: Re: global lexicals
Date: 
Message-ID: <ey3d6j1u9i6.fsf@cley.com>
* Rob Warnock wrote:

> which should be performant enough, yes?

I think so.  Someone mailed me to say that the obvious thing to do is
use the symbol's plist, so I do that now.  It feels like proper Lisp!
From: Gareth McCaughan
Subject: Re: global lexicals
Date: 
Message-ID: <slrnbb0g1p.on.Gareth.McCaughan@g.local>
Nils Goesche wrote:

> Why do you use a hash table?  Isn't something like
> 
> (defmacro defglex (var &optional value)
>   (let ((gs (gensym (symbol-name var))))
>     `(eval-when (:compile-toplevel :load-toplevel :execute)
>        (progn
>          (declaim (cons ,gs))
>          (defvar ,gs (list ,value))
>          (define-symbol-macro ,var (car ,gs))))))
> 
> good enough (and faster)?

I'm feeling very dim here. Why do you need the cons cell?
Why not just

    (defmacro defglex (var &optional value)
      (let ((gs (gensym (symbol-name var))))
        `(eval-when (:compile-toplevel :load-toplevel :execute)
           (progn
             (defvar ,gs ,value)
             (define-symbol-macro ,var ,gs)))))

instead?

-- 
Gareth McCaughan  ················@pobox.com
.sig under construc
From: Tim Bradshaw
Subject: Re: global lexicals
Date: 
Message-ID: <ey3of2n1ori.fsf@cley.com>
* Gareth McCaughan wrote:

>     (defmacro defglex (var &optional value)
>       (let ((gs (gensym (symbol-name var))))
>         `(eval-when (:compile-toplevel :load-toplevel :execute)
>            (progn
>              (defvar ,gs ,value)
>              (define-symbol-macro ,var ,gs)))))

I haven't thought about either this or the previous one, but I've just
realised that they're both hopelessly buggy because they don't
remember the gensym name, so multiple occurrences of DEFGLEX will do
something mutant and wrong: in particular:

  (defglex /x/ 1)
  (defun foo ()
    /x/)
  (defglex /x/ 2)
  (defun bar ()
    /x/)

Not only does the second occurrence cause /x/ to evaluate to 2 (which
might be justifiable if you think DEFGLEX should be like DEFPARAMETER
not DEFVAR), but it creates a completely different variable - FOO
`closes over' the original `binding', but BAR sees a new one.

My one had the first bug (now fixed - DEFGLEX is like DEFVAR), but not
the second.  Of course I can now reveal that this is why I used a
hashtable in the first place, honest.

--tim