From: Albert Krewinkel
Subject: generating new names in macro -- style question
Date: 
Message-ID: <m2prjs2abc.fsf@gmx.net>
I'm struggling with my sense of beauty here, having difficulties to
decide if the following is a good or bad idea.  A few comments  about the
following code with respect to good lisp style would be highly
appreciated.

I'm working with graphs (the mathematical structures) and wrote a couple
of functions which all take a graph as it's first argument.  To safe
myself some keystrokes, I wrote a macro which takes a graph as argument,
and provides curried functions of the graph-functions, also changing
the name to avoid confusion (and to safe a few more keystrokes).

Therefore instead of

(progn
  (graph-add-vertex some-graph 4)
  (graph-delete-vertex some-graph 5))

now I can do 

(with-graph (some-graph)
  (add-vertex 4)
  (delete-vertex 5)

This comes in very handy when I have to do multiple operations on the
same object.  However, it feels strange to generate new symbols, so I
wonder if there is a better way doing this kind of thing.  Global
variables would work, but that would break my attempt of doing things in
a functional manner.

Thanks
A


(defgeneric graph-add-vertex (graph ...) ...)

(defparameter *graph-functions*
  '(graph-add-vertex graph-delete-vertex graph-vertex-outdegree))

(defun graph-flet-curry (graph function new-function)
  `(,new-function (&rest args)
                  (apply #',function ,graph args)))


;; function `remove-symbol-prefix' alters a symbol by removing a prefix
;; (function definition not included for shortness)

(defmacro with-graph ((graph) &body body)
  (flet ((graph-flet-curry (graph function new-function)
           `(,new-function (&rest args)
                           (apply #',function ,graph args))))
    `(flet ,(loop for function in *graph-functions*
                  collect (graph-flet-curry graph
                                function
                                (remove-symbol-prefix function
                                       'graph)))
       ,@body)))

From: Kaz Kylheku
Subject: Re: generating new names in macro -- style question
Date: 
Message-ID: <20081231211740.149@gmail.com>
On 2008-12-16, Albert Krewinkel <·········@gmx.net> wrote:
> I'm struggling with my sense of beauty here, having difficulties to
> decide if the following is a good or bad idea.  A few comments  about the
> following code with respect to good lisp style would be highly
> appreciated.
>
> I'm working with graphs (the mathematical structures) and wrote a couple
> of functions which all take a graph as it's first argument.  To safe
> myself some keystrokes, I wrote a macro which takes a graph as argument,
> and provides curried functions of the graph-functions, also changing
> the name to avoid confusion (and to safe a few more keystrokes).
>
> Therefore instead of
>
> (progn
>   (graph-add-vertex some-graph 4)
>   (graph-delete-vertex some-graph 5))
>
> now I can do 
>
> (with-graph (some-graph)
>   (add-vertex 4)
>   (delete-vertex 5)
>
> This comes in very handy when I have to do multiple operations on the
> same object.  However, it feels strange to generate new symbols, so I
> wonder if there is a better way doing this kind of thing.  Global
> variables would work, but that would break my attempt of doing things in
> a functional manner.

You can't do this in a functional manner, because functional languages
typically don't have macros (because they are ``dirty''), and the contents of
your WITH-GRAPH are imperative anyway.

> Thanks
> A
>
>
> (defgeneric graph-add-vertex (graph ...) ...)
>
> (defparameter *graph-functions*
>   '(graph-add-vertex graph-delete-vertex graph-vertex-outdegree))
>
> (defun graph-flet-curry (graph function new-function)
>   `(,new-function (&rest args)
>                   (apply #',function ,graph args)))
>
>
> ;; function `remove-symbol-prefix' alters a symbol by removing a prefix
> ;; (function definition not included for shortness)
>
> (defmacro with-graph ((graph) &body body)
>   (flet ((graph-flet-curry (graph function new-function)
>            `(,new-function (&rest args)
>                            (apply #',function ,graph args))))
>     `(flet ,(loop for function in *graph-functions*
>                   collect (graph-flet-curry graph
>                                 function
>                                 (remove-symbol-prefix function
>                                        'graph)))
>        ,@body)))

I don't see why your list of *graph-functions* can't be a structure
that associates each long name with a short name. 

Also, that structure can describe the lambda lists better, so you
can generate more precise lambda lists than ``&rest args''.

Leave the ``atom smashing'' to physicists at CERN and elsewhere. :)

Your macro has some other problems.  You are assuming that the parameter
GRAPH is a symbol. This is false, because someone (probably yourself)
will eventually write (with-graph (get-graph-from-somewhere ...) ...).
Or even: (with-graph (get-graph-and-cause-side-effect x) ...).

Another thing you may end up doing is this: 
(with-graph (x) (lambda () (add-vertex 4))).  YOu want to be sure that the
closure returned from this block of code correctly captures the graph which was
passed into it at the time the closure was made. You probably don't want the
lambda capturing the variable X (which won't actually happen if X isn't a
lexical).

Your macro should take a graph-designating expression, generate a block of code
which, when entered, evaluates that expression, storing the resulting
graph object in a hidden local variable (gensym). Your functions should
then reference that gensym. Take a look at how WITH-SLOTS works for instance.

  (defun with-graph ((graph-designator) ,@body)
    (let ((graph-var (gensym "GRAPH-")))
      `(let ((,graph-var ,graph-designator))
         (flet ... ))))

Thus ,graph-designator appears only once in your macro template. In all
the other places, you write ,graph-var wherever you need the graph.
The gensym will be substituted in those places.
From: Albert Krewinkel
Subject: Re: generating new names in macro -- style question
Date: 
Message-ID: <m24p131skj.fsf@gmx.net>
Kaz Kylheku <········@gmail.com> writes:

> On 2008-12-16, Albert Krewinkel <·········@gmx.net> wrote:
>> [lots of strange stuff]
>>
>> This comes in very handy when I have to do multiple operations on the
>> same object.  However, it feels strange to generate new symbols, so I
>> wonder if there is a better way doing this kind of thing.  Global
>> variables would work, but that would break my attempt of doing things in
>> a functional manner.
>
> You can't do this in a functional manner, because functional languages
> typically don't have macros (because they are ``dirty''), and the contents of
> your WITH-GRAPH are imperative anyway.

Right.  I should have said thread-safe, as that's was what I really meant.

>> (defgeneric graph-add-vertex (graph ...) ...)
>>
>> (defparameter *graph-functions*
>>   '(graph-add-vertex graph-delete-vertex graph-vertex-outdegree))
>>
>> (defun graph-flet-curry (graph function new-function)
>>   `(,new-function (&rest args)
>>                   (apply #',function ,graph args)))
>>
>>
>> ;; function `remove-symbol-prefix' alters a symbol by removing a prefix
>> ;; (function definition not included for shortness)
>>
>> (defmacro with-graph ((graph) &body body)
>>   (flet ((graph-flet-curry (graph function new-function)
>>            `(,new-function (&rest args)
>>                            (apply #',function ,graph args))))
>>     `(flet ,(loop for function in *graph-functions*
>>                   collect (graph-flet-curry graph
>>                                 function
>>                                 (remove-symbol-prefix function
>>                                        'graph)))
>>        ,@body)))
>
> I don't see why your list of *graph-functions* can't be a structure
> that associates each long name with a short name. 
>
> Also, that structure can describe the lambda lists better, so you
> can generate more precise lambda lists than ``&rest args''.
>
> Leave the ``atom smashing'' to physicists at CERN and elsewhere. :)

I will.  Although, given the current state of the LHC: they won't be
doing that, for the next few month ;-)

> Your macro has some other problems.  You are assuming that the parameter
> GRAPH is a symbol. This is false, because someone (probably yourself)
> will eventually write (with-graph (get-graph-from-somewhere ...) ...).
> Or even: (with-graph (get-graph-and-cause-side-effect x) ...).
>
> Another thing you may end up doing is this: 
> (with-graph (x) (lambda () (add-vertex 4))).  YOu want to be sure that the
> closure returned from this block of code correctly captures the graph which was
> passed into it at the time the closure was made. You probably don't want the
> lambda capturing the variable X (which won't actually happen if X isn't a
> lexical).
>
> Your macro should take a graph-designating expression, generate a block of code
> which, when entered, evaluates that expression, storing the resulting
> graph object in a hidden local variable (gensym). Your functions should
> then reference that gensym. Take a look at how WITH-SLOTS works for instance.
>
>   (defun with-graph ((graph-designator) ,@body)
>     (let ((graph-var (gensym "GRAPH-")))
>       `(let ((,graph-var ,graph-designator))
>          (flet ... ))))
>
> Thus ,graph-designator appears only once in your macro template. In all
> the other places, you write ,graph-var wherever you need the graph.
> The gensym will be substituted in those places.

Thanks a lot for the help.
From: Madhu
Subject: Re: generating new names in macro -- style question
Date: 
Message-ID: <m3oczc7vcp.fsf@moon.robolove.meer.net>
* Albert Krewinkel <··············@gmx.net> :
Wrote on Mon, 15 Dec 2008 17:11:35 -0800:

| I'm working with graphs (the mathematical structures) and wrote a couple
| of functions which all take a graph as it's first argument.  To safe
| myself some keystrokes, I wrote a macro which takes a graph as argument,
| and provides curried functions of the graph-functions, also changing
| the name to avoid confusion (and to safe a few more keystrokes).
|
| Therefore instead of
|
| (progn
|   (graph-add-vertex some-graph 4)
|   (graph-delete-vertex some-graph 5))
|
| (with-graph (some-graph)
|   (add-vertex 4)
|   (delete-vertex 5)
|
| This comes in very handy when I have to do multiple operations on the
| same object.  However, it feels strange to generate new symbols, so I
| wonder if there is a better way doing this kind of thing.  Global
| variables would work, but that would break my attempt of doing things in
| a functional manner.

This functional aesthetic does not apply to common lisp in many cases.
There are clear advantages in the CL approach:

(defvar *graph* nil "Default graph target for all operations if non-NULL.")

(defun add-vertex (vertex &optional (graph *graph*)) ...)
(defun delete-vertex (vertex &optional (graph *graph*)) ...)

All you have done is switch the argument order. You get back your
with-graph macro in this form:

(defmacro with-graph (graph &body body) `(let ((*graph* graph)) ,@body))

--
Madhu
From: Albert Krewinkel
Subject: Re: generating new names in macro -- style question
Date: 
Message-ID: <m2ljug27tw.fsf@gmx.net>
Madhu <·······@meer.net> writes:

> * Albert Krewinkel <··············@gmx.net> :
> Wrote on Mon, 15 Dec 2008 17:11:35 -0800:
>
> | I'm working with graphs (the mathematical structures) and wrote a couple
> | of functions which all take a graph as it's first argument.  To safe
> | myself some keystrokes, I wrote a macro which takes a graph as argument,
> | and provides curried functions of the graph-functions, also changing
> | the name to avoid confusion (and to safe a few more keystrokes).
> |
> | Therefore instead of
> |
> | (progn
> |   (graph-add-vertex some-graph 4)
> |   (graph-delete-vertex some-graph 5))
> |
> | (with-graph (some-graph)
> |   (add-vertex 4)
> |   (delete-vertex 5)
> |
> | This comes in very handy when I have to do multiple operations on the
> | same object.  However, it feels strange to generate new symbols, so I
> | wonder if there is a better way doing this kind of thing.  Global
> | variables would work, but that would break my attempt of doing things in
> | a functional manner.
>
> This functional aesthetic does not apply to common lisp in many cases.
> There are clear advantages in the CL approach:
>
> (defvar *graph* nil "Default graph target for all operations if non-NULL.")
>
> (defun add-vertex (vertex &optional (graph *graph*)) ...)
> (defun delete-vertex (vertex &optional (graph *graph*)) ...)
>
> All you have done is switch the argument order. You get back your
> with-graph macro in this form:
>
> (defmacro with-graph (graph &body body) `(let ((*graph* graph)) ,@body))

True, but it also renders &rest useless.  Imagine, e.g. a hypergraph,
where an edge may connect 0 or more edges.  Having
  (defgeneric vertices-adjacent-p (vertices &optional graph) ...)
is pretty ugly, 
  (defgeneric vertices-adjacent-p (graph &rest vertices) ...)
is much nicer.

Also, method-dispatching on the graph requires an additional
helper-function `graph-vertices-adjacent-p', so we are right we started.

Anyway, thanks for the answer.
From: Madhu
Subject: Re: generating new names in macro -- style question
Date: 
Message-ID: <m3fxko7szx.fsf@moon.robolove.meer.net>
* Albert Krewinkel <··············@gmx.net> :
Wrote on Mon, 15 Dec 2008 18:05:15 -0800:

| Madhu <·······@meer.net> writes:
|> * Albert Krewinkel <··············@gmx.net> :
|> Wrote on Mon, 15 Dec 2008 17:11:35 -0800:
|> | This comes in very handy when I have to do multiple operations on the
|> | same object.  However, it feels strange to generate new symbols, so I
|> | wonder if there is a better way doing this kind of thing.  Global
|> | variables would work, but that would break my attempt of doing things in
|> | a functional manner.
|>
|> This functional aesthetic does not apply to common lisp in many cases.
|> There are clear advantages in the CL approach:
|>
|> (defvar *graph* nil "Default graph target for all operations if non-NULL.")
|>
|> (defun add-vertex (vertex &optional (graph *graph*)) ...)
|> (defun delete-vertex (vertex &optional (graph *graph*)) ...)
|>
|> All you have done is switch the argument order. You get back your
|> with-graph macro in this form:
|>
|> (defmacro with-graph (graph &body body) `(let ((*graph* graph)) ,@body))
|
| True, but it also renders &rest useless.  Imagine, e.g. a hypergraph,
| where an edge may connect 0 or more edges.  Having
|   (defgeneric vertices-adjacent-p (vertices &optional graph) ...)
| is pretty ugly, 
|   (defgeneric vertices-adjacent-p (graph &rest vertices) ...)
| is much nicer.

I've gone back and forth on this on many problems with this structure.
My current style is to write

 VERTICES-ADJACENT-P (GRAPH VERTICES)

as the basic implementation function, and add the syntactically a
friendlier function as an ordinary function which calls this after
massaging parameters.


| Also, method-dispatching on the graph requires an additional
| helper-function `graph-vertices-adjacent-p', so we are right we
| started.

I suspect you would need a helper function to do dispatch anyway if
you wanted &REST.  (This appears to be a different concern)

Anyway the basic point I wanted to make was it was NOT WRONG to use
specials in implementing something which lets you write your code in a
functional style.  At some point all the code in "functional languages"
get implemented using "non-functional" devices.  There is no point in
restricting the devices you can use when they are already available (and
can be used somewhat elegantly).

[NOTE In CL as soon as you wrote that macro, you are already the
language implementor for the rest of your program]

--
Madhu
From: Tamas K Papp
Subject: Re: generating new names in macro -- style question
Date: 
Message-ID: <6qpmaoFdv2emU1@mid.individual.net>
On Tue, 16 Dec 2008 07:08:14 +0530, Madhu wrote:

> All you have done is switch the argument order. You get back your
> with-graph macro in this form:
> 
> (defmacro with-graph (graph &body body) `(let ((*graph* graph)) ,@body))

Is this thread-safe?  What if a similar expression is being evaluated in 
another thread, but for a different graph?

Tamas
From: Alessio Stalla
Subject: Doubts about special bindings
Date: 
Message-ID: <ffd3014c-78e0-424f-8742-62a934acf7d2@s9g2000prg.googlegroups.com>
On Dec 16, 1:47 pm, Tamas K Papp <······@gmail.com> wrote:
> On Tue, 16 Dec 2008 07:08:14 +0530, Madhu wrote:
> > All you have done is switch the argument order. You get back your
> > with-graph macro in this form:
>
> > (defmacro with-graph (graph &body body) `(let ((*graph* graph)) ,@body))
>
> Is this thread-safe?  What if a similar expression is being evaluated in
> another thread, but for a different graph?

In most Lisp implementations I know of, local special bindings
(introduced by let) are per-thread.

Quite off-topic, but I have another doubt wrt specials that comes to
my mind now:

(defvar *var* 42)
(defun f (&optional *var*) (print *var*))

is (f) guaranteed to return 42 (provided no-one sets *var*, of
course), both in interpreted and compiled code?
is (let ((*var* 43)) (f)) guaranteed to return 43, both... well you
have understood, don't you? ;)

Alessio
From: Joshua Taylor
Subject: Re: Doubts about special bindings
Date: 
Message-ID: <ea705324-5695-4d5d-973b-deed71bc4408@q30g2000prq.googlegroups.com>
On Dec 16, 9:13 am, Alessio Stalla <·············@gmail.com> wrote:
> On Dec 16, 1:47 pm, Tamas K Papp <······@gmail.com> wrote:
>
> > On Tue, 16 Dec 2008 07:08:14 +0530, Madhu wrote:
> > > All you have done is switch the argument order. You get back your
> > > with-graph macro in this form:
>
> > > (defmacro with-graph (graph &body body) `(let ((*graph* graph)) ,@body))
>
> > Is this thread-safe?  What if a similar expression is being evaluated in
> > another thread, but for a different graph?
>
> In most Lisp implementations I know of, local special bindings
> (introduced by let) are per-thread.
>
> Quite off-topic, but I have another doubt wrt specials that comes to
> my mind now:
>
> (defvar *var* 42)
> (defun f (&optional *var*) (print *var*))
>
> is (f) guaranteed to return 42 (provided no-one sets *var*, of
> course), both in interpreted and compiled code?
> is (let ((*var* 43)) (f)) guaranteed to return 43, both... well you
> have understood, don't you? ;)
>
> Alessio

I think it was just a casual typo, but just to be clear, you'll only
get 42 and 43 if that optional also has a default value which happens
to be *var* as well. Otherwise you'll just get NIL.

CL-USER 1 > (defvar *var* 42)
*VAR*

CL-USER 2 > (defun f (&optional *var*) (print *var*))
F

CL-USER 3 > (f)
NIL ;; with no default value, *var* gets bound to NIL
NIL

CL-USER 4 > (let ((*var* 43)) (f))
NIL ;; with no default value, *var* gets bound to NIL
NIL

CL-USER 5 > (defun f2 (&optional (*var* *var*)) (print *var*))
F2

CL-USER 6 > (f2)
42 ;; but with default value *var*, *var* is bound to the same value
42

CL-USER 7 > (let ((*var* 43)) (f2))
43
43

//JT
From: Alessio Stalla
Subject: Re: Doubts about special bindings
Date: 
Message-ID: <972a3211-55f5-49d7-bea2-43d38aec4d07@z6g2000pre.googlegroups.com>
On 16 Dic, 15:43, Joshua Taylor <···········@gmail.com> wrote:
> I think it was just a casual typo, but just to be clear, you'll only
> get 42 and 43 if that optional also has a default value which happens
> to be *var* as well. Otherwise you'll just get NIL.

Duh, you're right; but it was not properly a typo, it was more of an
oversight. Actually my doubt came from the fact that I find myself
sometimes writing

(defun f (x y &optional (context *context*))
  (let ((*context* context))
     ...code using *context*...))

which, as you have taught me, can be written simply as

(defun f (x y &optional (*context* *context*))
   ...code using *context*...)

So, thanks for the clarification, and sorry for going OT.

Alessio

> CL-USER 1 > (defvar *var* 42)
> *VAR*
>
> CL-USER 2 > (defun f (&optional *var*) (print *var*))
> F
>
> CL-USER 3 > (f)
> NIL ;; with no default value, *var* gets bound to NIL
> NIL
>
> CL-USER 4 > (let ((*var* 43)) (f))
> NIL ;; with no default value, *var* gets bound to NIL
> NIL
>
> CL-USER 5 > (defun f2 (&optional (*var* *var*)) (print *var*))
> F2
>
> CL-USER 6 > (f2)
> 42 ;; but with default value *var*, *var* is bound to the same value
> 42
>
> CL-USER 7 > (let ((*var* 43)) (f2))
> 43
> 43
>
> //JT
From: Pascal Costanza
Subject: Re: Doubts about special bindings
Date: 
Message-ID: <6qprqrFe4ib0U1@mid.individual.net>
Alessio Stalla wrote:
> On Dec 16, 1:47 pm, Tamas K Papp <······@gmail.com> wrote:
>> On Tue, 16 Dec 2008 07:08:14 +0530, Madhu wrote:
>>> All you have done is switch the argument order. You get back your
>>> with-graph macro in this form:
>>> (defmacro with-graph (graph &body body) `(let ((*graph* graph)) ,@body))
>> Is this thread-safe?  What if a similar expression is being evaluated in
>> another thread, but for a different graph?
> 
> In most Lisp implementations I know of, local special bindings
> (introduced by let) are per-thread.
> 
> Quite off-topic, but I have another doubt wrt specials that comes to
> my mind now:
> 
> (defvar *var* 42)
> (defun f (&optional *var*) (print *var*))
> 
> is (f) guaranteed to return 42 (provided no-one sets *var*, of
> course), both in interpreted and compiled code?

If nobody sets *var* and nobody rebinds it, yes.

> is (let ((*var* 43)) (f)) guaranteed to return 43, both... well you
> have understood, don't you? ;)

Yes, guaranteed to return 43.


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: Kaz Kylheku
Subject: Re: Doubts about special bindings
Date: 
Message-ID: <20090101151216.655@gmail.com>
On 2008-12-16, Alessio Stalla <·············@gmail.com> wrote:
> On Dec 16, 1:47 pm, Tamas K Papp <······@gmail.com> wrote:
>> On Tue, 16 Dec 2008 07:08:14 +0530, Madhu wrote:
>> > All you have done is switch the argument order. You get back your
>> > with-graph macro in this form:
>>
>> > (defmacro with-graph (graph &body body) `(let ((*graph* graph)) ,@body))
>>
>> Is this thread-safe?  What if a similar expression is being evaluated in
>> another thread, but for a different graph?
>
> In most Lisp implementations I know of, local special bindings
> (introduced by let) are per-thread.
>
> Quite off-topic, but I have another doubt wrt specials that comes to
> my mind now:
>
> (defvar *var* 42)
> (defun f (&optional *var*) (print *var*))
>
> is (f) guaranteed to return 42 (provided no-one sets *var*, of
> course), both in interpreted and compiled code?

(F) does not return 42 but NIL.  *var* is locally bound, and not given
a value, so it is initialized to NIL.

There is nothing special about an &OPTIONAL parameter. It's just another local
variable. 

The binding of an &OPTIONAL formal parameter takes place whether or not the
actual argument is specified. If the argument is not specified, then the
parameter receives the value NIL.

Thus if you want (F) to return 42, you have to specify that argument
value, i.e. (F 42).

> is (let ((*var* 43)) (f)) guaranteed to return 43, both... well you
> have understood, don't you? ;)

Nope, still NIL. See above.
From: Madhu
Subject: Re: generating new names in macro -- style question
Date: 
Message-ID: <m38wqg6x0x.fsf@moon.robolove.meer.net>
* Tamas K Papp <··············@mid.individual.net> :
Wrote on 16 Dec 2008 12:47:20 GMT:

| On Tue, 16 Dec 2008 07:08:14 +0530, Madhu wrote:
|
|> All you have done is switch the argument order. You get back your
|> with-graph macro in this form:
|> 
|> (defmacro with-graph (graph &body body) `(let ((*graph* graph)) ,@body))
|
| Is this thread-safe?  What if a similar expression is being evaluated in 
| another thread, but for a different graph?

Check your lisp implementation's documentation on threads: if it makes
special variables thread local, I assume it is safe.

--
Madhu
From: Tamas K Papp
Subject: Re: generating new names in macro -- style question
Date: 
Message-ID: <6qq3huFdv2emU2@mid.individual.net>
On Tue, 16 Dec 2008 19:29:42 +0530, Madhu wrote:

> * Tamas K Papp <··············@mid.individual.net> : Wrote on 16 Dec
> 2008 12:47:20 GMT:
> 
> | On Tue, 16 Dec 2008 07:08:14 +0530, Madhu wrote: |
> |> All you have done is switch the argument order. You get back your |>
> with-graph macro in this form:
> |>
> |> (defmacro with-graph (graph &body body) `(let ((*graph* graph))
> ,@body)) |
> | Is this thread-safe?  What if a similar expression is being evaluated
> in | another thread, but for a different graph?
> 
> Check your lisp implementation's documentation on threads: if it makes
> special variables thread local, I assume it is safe.

Yes, in SBCL it is safe.  Thanks for the clarification.

Tamas
From: Albert Krewinkel
Subject: Re: generating new names in macro -- style question
Date: 
Message-ID: <m28wqf1t4h.fsf@gmx.net>
Tamas K Papp <······@gmail.com> writes:

> On Tue, 16 Dec 2008 19:29:42 +0530, Madhu wrote:
>
>> * Tamas K Papp <··············@mid.individual.net> : Wrote on 16 Dec
>> 2008 12:47:20 GMT:
>> 
>> | On Tue, 16 Dec 2008 07:08:14 +0530, Madhu wrote: |
>> |> All you have done is switch the argument order. You get back your |>
>> with-graph macro in this form:
>> |>
>> |> (defmacro with-graph (graph &body body) `(let ((*graph* graph))
>> ,@body)) |
>> | Is this thread-safe?  What if a similar expression is being evaluated
>> in | another thread, but for a different graph?
>> 
>> Check your lisp implementation's documentation on threads: if it makes
>> special variables thread local, I assume it is safe.
>
> Yes, in SBCL it is safe.  Thanks for the clarification.
>
> Tamas

Cool.  That was one of the things I worried about when I came up with
my question.  So "functional" in my original question should have read
"thread safe". D'OH

Thanks for the help.