Account Options

  1. Sign in
The old Google Groups will be going away soon, but your browser is incompatible with the new version.
Google Groups Home
« Groups Home
generating new names in macro -- style question
There are currently too many topics in this group that display first. To make this topic appear first, remove this option from another topic.
There was an error processing your request. Please try again.
flag
  15 messages - Collapse all  -  Translate all to Translated (View all originals)
The group you are posting to is a Usenet group. Messages posted to this group will make your email address visible to anyone on the Internet.
Your reply message has not been sent.
Your post was successful
 
From:
To:
Cc:
Followup To:
Add Cc | Add Followup-to | Edit Subject
Subject:
Validation:
For verification purposes please type the characters you see in the picture below or the numbers you hear by clicking the accessibility icon. Listen and type the numbers you hear
 
Albert Krewinkel  
View profile  
 More options Dec 15 2008, 8:11 pm
Newsgroups: comp.lang.lisp
From: Albert Krewinkel <krewin...@gmx.net>
Date: Mon, 15 Dec 2008 17:11:35 -0800
Local: Mon, Dec 15 2008 8:11 pm
Subject: generating new names in macro -- style question
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)))


 
You must Sign in before you can post messages.
To post a message you must first join this group.
Please update your nickname on the subscription settings page before posting.
You do not have the permission required to post.
Madhu  
View profile  
 More options Dec 15 2008, 8:38 pm
Newsgroups: comp.lang.lisp
From: Madhu <enom...@meer.net>
Date: Tue, 16 Dec 2008 07:08:14 +0530
Local: Mon, Dec 15 2008 8:38 pm
Subject: Re: generating new names in macro -- style question

* Albert Krewinkel <m2prjs2abc....@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


 
You must Sign in before you can post messages.
To post a message you must first join this group.
Please update your nickname on the subscription settings page before posting.
You do not have the permission required to post.
Albert Krewinkel  
View profile  
 More options Dec 15 2008, 9:05 pm
Newsgroups: comp.lang.lisp
From: Albert Krewinkel <krewin...@gmx.net>
Date: Mon, 15 Dec 2008 18:05:15 -0800
Local: Mon, Dec 15 2008 9:05 pm
Subject: Re: generating new names in macro -- style question

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.


 
You must Sign in before you can post messages.
To post a message you must first join this group.
Please update your nickname on the subscription settings page before posting.
You do not have the permission required to post.
Madhu  
View profile  
 More options Dec 15 2008, 9:29 pm
Newsgroups: comp.lang.lisp
From: Madhu <enom...@meer.net>
Date: Tue, 16 Dec 2008 07:59:06 +0530
Local: Mon, Dec 15 2008 9:29 pm
Subject: Re: generating new names in macro -- style question

* Albert Krewinkel <m2ljug27tw....@gmx.net> :
Wrote on Mon, 15 Dec 2008 18:05:15 -0800:

| Madhu <enom...@meer.net> writes:

|> * Albert Krewinkel <m2prjs2abc....@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


 
You must Sign in before you can post messages.
To post a message you must first join this group.
Please update your nickname on the subscription settings page before posting.
You do not have the permission required to post.
Kaz Kylheku  
View profile  
 More options Dec 16 2008, 12:01 am
Newsgroups: comp.lang.lisp
From: Kaz Kylheku <kkylh...@gmail.com>
Date: Tue, 16 Dec 2008 05:01:21 +0000 (UTC)
Local: Tues, Dec 16 2008 12:01 am
Subject: Re: generating new names in macro -- style question
On 2008-12-16, Albert Krewinkel <krewin...@gmx.net> wrote:

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.

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.


 
You must Sign in before you can post messages.
To post a message you must first join this group.
Please update your nickname on the subscription settings page before posting.
You do not have the permission required to post.
Tamas K Papp  
View profile  
 More options Dec 16 2008, 7:47 am
Newsgroups: comp.lang.lisp
From: Tamas K Papp <tkp...@gmail.com>
Date: 16 Dec 2008 12:47:20 GMT
Local: Tues, Dec 16 2008 7:47 am
Subject: Re: generating new names in macro -- style question

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


 
You must Sign in before you can post messages.
To post a message you must first join this group.
Please update your nickname on the subscription settings page before posting.
You do not have the permission required to post.
Madhu  
View profile  
 More options Dec 16 2008, 8:59 am
Newsgroups: comp.lang.lisp
From: Madhu <enom...@meer.net>
Date: Tue, 16 Dec 2008 19:29:42 +0530
Local: Tues, Dec 16 2008 8:59 am
Subject: Re: generating new names in macro -- style question

* Tamas K Papp <6qpmaoFdv2e...@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


 
You must Sign in before you can post messages.
To post a message you must first join this group.
Please update your nickname on the subscription settings page before posting.
You do not have the permission required to post.
Discussion subject changed to "Doubts about special bindings" by Alessio Stalla
Alessio Stalla  
View profile  
 More options Dec 16 2008, 9:13 am
Newsgroups: comp.lang.lisp
From: Alessio Stalla <alessiosta...@gmail.com>
Date: Tue, 16 Dec 2008 06:13:29 -0800 (PST)
Local: Tues, Dec 16 2008 9:13 am
Subject: Doubts about special bindings
On Dec 16, 1:47 pm, Tamas K Papp <tkp...@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


 
You must Sign in before you can post messages.
To post a message you must first join this group.
Please update your nickname on the subscription settings page before posting.
You do not have the permission required to post.
Pascal Costanza  
View profile  
 More options Dec 16 2008, 9:21 am
Newsgroups: comp.lang.lisp
From: Pascal Costanza <p...@p-cos.net>
Date: Tue, 16 Dec 2008 15:21:15 +0100
Local: Tues, Dec 16 2008 9:21 am
Subject: Re: Doubts about special bindings

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/


 
You must Sign in before you can post messages.
To post a message you must first join this group.
Please update your nickname on the subscription settings page before posting.
You do not have the permission required to post.
Joshua Taylor  
View profile  
 More options Dec 16 2008, 9:43 am
Newsgroups: comp.lang.lisp
From: Joshua Taylor <joshuaaa...@gmail.com>
Date: Tue, 16 Dec 2008 06:43:22 -0800 (PST)
Local: Tues, Dec 16 2008 9:43 am
Subject: Re: Doubts about special bindings
On Dec 16, 9:13 am, Alessio Stalla <alessiosta...@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.

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


 
You must Sign in before you can post messages.
To post a message you must first join this group.
Please update your nickname on the subscription settings page before posting.
You do not have the permission required to post.
Discussion subject changed to "generating new names in macro -- style question" by Tamas K Papp
Tamas K Papp  
View profile  
 More options Dec 16 2008, 11:33 am
Newsgroups: comp.lang.lisp
From: Tamas K Papp <tkp...@gmail.com>
Date: 16 Dec 2008 16:33:02 GMT
Local: Tues, Dec 16 2008 11:33 am
Subject: Re: generating new names in macro -- style question

On Tue, 16 Dec 2008 19:29:42 +0530, Madhu wrote:
> * Tamas K Papp <6qpmaoFdv2e...@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


 
You must Sign in before you can post messages.
To post a message you must first join this group.
Please update your nickname on the subscription settings page before posting.
You do not have the permission required to post.
Discussion subject changed to "Doubts about special bindings" by Kaz Kylheku
Kaz Kylheku  
View profile  
 More options Dec 16 2008, 4:34 pm
Newsgroups: comp.lang.lisp
From: Kaz Kylheku <kkylh...@gmail.com>
Date: Tue, 16 Dec 2008 21:34:00 +0000 (UTC)
Subject: Re: Doubts about special bindings
On 2008-12-16, Alessio Stalla <alessiosta...@gmail.com> wrote:

(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.

 
You must Sign in before you can post messages.
To post a message you must first join this group.
Please update your nickname on the subscription settings page before posting.
You do not have the permission required to post.
Alessio Stalla  
View profile  
 More options Dec 16 2008, 6:19 pm
Newsgroups: comp.lang.lisp
From: Alessio Stalla <alessiosta...@gmail.com>
Date: Tue, 16 Dec 2008 15:19:21 -0800 (PST)
Local: Tues, Dec 16 2008 6:19 pm
Subject: Re: Doubts about special bindings
On 16 Dic, 15:43, Joshua Taylor <joshuaaa...@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


 
You must Sign in before you can post messages.
To post a message you must first join this group.
Please update your nickname on the subscription settings page before posting.
You do not have the permission required to post.
Discussion subject changed to "generating new names in macro -- style question" by Albert Krewinkel
Albert Krewinkel  
View profile  
 More options Dec 16 2008, 8:35 pm
Newsgroups: comp.lang.lisp
From: Albert Krewinkel <krewin...@gmx.net>
Date: Tue, 16 Dec 2008 17:35:10 -0800
Local: Tues, Dec 16 2008 8:35 pm
Subject: Re: generating new names in macro -- style question
Tamas K Papp <tkp...@gmail.com> writes:

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.


 
You must Sign in before you can post messages.
To post a message you must first join this group.
Please update your nickname on the subscription settings page before posting.
You do not have the permission required to post.
Albert Krewinkel  
View profile  
 More options Dec 16 2008, 8:47 pm
Newsgroups: comp.lang.lisp
From: Albert Krewinkel <krewin...@gmx.net>
Date: Tue, 16 Dec 2008 17:47:08 -0800
Local: Tues, Dec 16 2008 8:47 pm
Subject: Re: generating new names in macro -- style question

Kaz Kylheku <kkylh...@gmail.com> writes:
> On 2008-12-16, Albert Krewinkel <krewin...@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.

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

Thanks a lot for the help.

 
You must Sign in before you can post messages.
To post a message you must first join this group.
Please update your nickname on the subscription settings page before posting.
You do not have the permission required to post.
End of messages
« Back to Discussions « Newer topic     Older topic »