From: Greg Buchholz
Subject: concatenate symbols (token pasting)
Date: 
Message-ID: <1145398567.360936.156330@u72g2000cwu.googlegroups.com>
    I'm trying to overload some arithmetic functions, and I need a
little help in writing a macro to help me out.  Instead of writing lots
of boilerplate like...

(shadow '+)
(defmethod + (x y)
  (cl:+ x y))
(defmethod + ((x symbol) y)
  `(+ ,x ,y))
(defmethod + (x (y symbol))
  `(+ ,x ,y))

...etc., I want to create a macro to help automate this.  I've tried
several different things, and my latest attempt fails because I don't
know how to concatenate symbols together.  That is, I want to create a
fully qualified symbol like "cl:+" from a simple "+".  Here's the
current state of my macro...

(defmacro create-diff (xs)
  `(progn ,@(reduce #'append
    (mapcar #'(lambda (x)
               `((shadow ',x)
                 (defmethod ,x (a b)
                   (,(SOMETHING-GOES-HERE x) a b))
                 (defmethod ,x ((a symbol) b)
                   `(,',x ,a ,b))
                 (defmethod ,x (a (b symbol))
                   `(,',x ,a ,b)))) xs))))

...I've tried a few alternatives for SOMETHING-GOES-HERE, including
variations on "make-symbol", but something like...

(make-symbol (concatenate 'string "cl:" (format nil "~A" '+)))

...results in "#:|cl:+|" which doesn't work.  So what's the right way
to get this working?

Thanks,

Greg Buchholz

From: Bill Atkins
Subject: Re: concatenate symbols (token pasting)
Date: 
Message-ID: <87d5fer05b.fsf@rpi.edu>
"Greg Buchholz" <················@yahoo.com> writes:

.>     I'm trying to overload some arithmetic functions, and I need a
> little help in writing a macro to help me out.  Instead of writing lots
> of boilerplate like...
>
> (shadow '+)
> (defmethod + (x y)
>   (cl:+ x y))
> (defmethod + ((x symbol) y)
>   `(+ ,x ,y))
> (defmethod + (x (y symbol))
>   `(+ ,x ,y))
>
> ...etc., I want to create a macro to help automate this.  I've tried
> several different things, and my latest attempt fails because I don't
> know how to concatenate symbols together.  That is, I want to create a
> fully qualified symbol like "cl:+" from a simple "+".  Here's the
> current state of my macro...
>
> (defmacro create-diff (xs)
>   `(progn ,@(reduce #'append
>     (mapcar #'(lambda (x)
>                `((shadow ',x)
>                  (defmethod ,x (a b)
>                    (,(SOMETHING-GOES-HERE x) a b))
>                  (defmethod ,x ((a symbol) b)
>                    `(,',x ,a ,b))
>                  (defmethod ,x (a (b symbol))
>                    `(,',x ,a ,b)))) xs))))
>
> ...I've tried a few alternatives for SOMETHING-GOES-HERE, including
> variations on "make-symbol", but something like...
>
> (make-symbol (concatenate 'string "cl:" (format nil "~A" '+)))
>
> ...results in "#:|cl:+|" which doesn't work.  So what's the right way
> to get this working?
>
> Thanks,
>
> Greg Buchholz

By default, READ converts all symbols to a canonical uppercase string.
So the symbols 'cl and 'CL are indeed EQ, but they are both read in as
the same symbol with print-name "CL".  Uppercasing your "cl:" should
do the trick.

However, the ANSI standard forbids redefining functions in the
COMMON-LISP (CL) package.  You should shadow the symbol and redefine
it only in the current package.  So your question is sort of not
relevant. :)

I guess I don't fully understand what problem this macro is solving,
either.

--
Bill
From: Greg Buchholz
Subject: Re: concatenate symbols (token pasting)
Date: 
Message-ID: <1145400266.919982.11820@i39g2000cwa.googlegroups.com>
Bill Atkins wrote:
> By default, READ converts all symbols to a canonical uppercase string.
> So the symbols 'cl and 'CL are indeed EQ, but they are both read in as
> the same symbol with print-name "CL".  Uppercasing your "cl:" should
> do the trick.

Hmm.  That doesn't fix my problem.

> However, the ANSI standard forbids redefining functions in the
> COMMON-LISP (CL) package.  You should shadow the symbol and redefine
> it only in the current package.

Isn't that what I'm doing?

> I guess I don't fully understand what problem this macro is solving,
> either.

The snippet of code below does what I want, but it seems like there's a
whole lot of needless repetition.  I want a macro that I can invoke
like "(create-diff (+ - * /))" and have it produce the same code.

(shadow '+)
(defmethod + (x y)
  (cl:+ x y))
(defmethod + ((x symbol) y)
  `(+ ,x ,y))
(defmethod + (x (y symbol))
  `(+ ,x ,y))

(shadow '-)
(defmethod - (x y)
  (cl:- x y))
(defmethod - ((x symbol) y)
  `(- ,x ,y))
(defmethod - (x (y symbol))
  `(- ,x ,y))

(shadow '*)
(defmethod * (x y)
  (cl:* x y))
(defmethod * ((x symbol) y)
  `(* ,x ,y))
(defmethod * (x (y symbol))
  `(* ,x ,y))

(shadow '/)
(defmethod / (x y)
  (cl:/ x y))
(defmethod / ((x symbol) y)
  `(/ ,x ,y))
(defmethod / (x (y symbol))
  `(/ ,x ,y))


Thanks,

Greg Buchholz
From: Bill Atkins
Subject: Re: concatenate symbols (token pasting)
Date: 
Message-ID: <877j5mqxvn.fsf@rpi.edu>
"Greg Buchholz" <················@yahoo.com> writes:

> Bill Atkins wrote:
>> By default, READ converts all symbols to a canonical uppercase string.
>> So the symbols 'cl and 'CL are indeed EQ, but they are both read in as
>> the same symbol with print-name "CL".  Uppercasing your "cl:" should
>> do the trick.
>
> Hmm.  That doesn't fix my problem.
>
>> However, the ANSI standard forbids redefining functions in the
>> COMMON-LISP (CL) package.  You should shadow the symbol and redefine
>> it only in the current package.
>
> Isn't that what I'm doing?

Yes. :)  My mistake.

>> I guess I don't fully understand what problem this macro is solving,
>> either.
>
> The snippet of code below does what I want, but it seems like there's a
> whole lot of needless repetition.  I want a macro that I can invoke
> like "(create-diff (+ - * /))" and have it produce the same code.
>
> (shadow '+)
> (defmethod + (x y)
>   (cl:+ x y))
> (defmethod + ((x symbol) y)
>   `(+ ,x ,y))
> (defmethod + (x (y symbol))
>   `(+ ,x ,y))
>
> (shadow '-)
> (defmethod - (x y)
>   (cl:- x y))
> (defmethod - ((x symbol) y)
>   `(- ,x ,y))
> (defmethod - (x (y symbol))
>   `(- ,x ,y))
>
> (shadow '*)
> (defmethod * (x y)
>   (cl:* x y))
> (defmethod * ((x symbol) y)
>   `(* ,x ,y))
> (defmethod * (x (y symbol))
>   `(* ,x ,y))
>
> (shadow '/)
> (defmethod / (x y)
>   (cl:/ x y))
> (defmethod / ((x symbol) y)
>   `(/ ,x ,y))
> (defmethod / (x (y symbol))
>   `(/ ,x ,y))
>
>
> Thanks,
>
> Greg Buchholz
From: Barry Margolin
Subject: Re: concatenate symbols (token pasting)
Date: 
Message-ID: <barmar-171B22.00241719042006@comcast.dca.giganews.com>
In article <························@u72g2000cwu.googlegroups.com>,
 "Greg Buchholz" <················@yahoo.com> wrote:

>     I'm trying to overload some arithmetic functions, and I need a
> little help in writing a macro to help me out.  Instead of writing lots
> of boilerplate like...
> 
> (shadow '+)
> (defmethod + (x y)
>   (cl:+ x y))
> (defmethod + ((x symbol) y)
>   `(+ ,x ,y))

Is that really what you intend?  That returns a list rather than adding 
things.  I suspect you mean something like:

(defmethod + ((x symbol) y)
  (+ (symbol-value x) y))
or
(defmethod + ((x symbol) y)
  (eval `(+ ,x ',y)))

-- 
Barry Margolin, ······@alum.mit.edu
Arlington, MA
*** PLEASE post questions in newsgroups, not directly to me ***
*** PLEASE don't copy me on replies, I'll read them in the group ***
From: Greg Buchholz
Subject: Re: concatenate symbols (token pasting)
Date: 
Message-ID: <1145456172.096522.229410@z34g2000cwc.googlegroups.com>
Barry Margolin wrote:
> Is that really what you intend?  That returns a list rather than adding
> things.

   Yup.  That's really what I want.  If an expression has a symbol in
it, I want to keep it in a symbolic representation.  Lists seem as good
as anything else.

Greg Buchholz
From: Rainer Joswig
Subject: Re: concatenate symbols (token pasting)
Date: 
Message-ID: <C06B3D0E.38556%joswig@lisp.de>
Am 19.04.2006 0:16 Uhr schrieb "Greg Buchholz" unter
<················@yahoo.com> in
························@u72g2000cwu.googlegroups.com:

>     I'm trying to overload some arithmetic functions, and I need a
> little help in writing a macro to help me out.  Instead of writing lots
> of boilerplate like...
> 
> (shadow '+)
> (defmethod + (x y)
>   (cl:+ x y))
> (defmethod + ((x symbol) y)
>   `(+ ,x ,y))
> (defmethod + (x (y symbol))
>   `(+ ,x ,y))
> 
> ...etc., I want to create a macro to help automate this.  I've tried
> 
> several different things, and my latest attempt fails because I don't
> know how to concatenate symbols together.  That is, I want to create a
> fully qualified symbol like "cl:+" from a simple "+".  Here's the
> current state of my macro...
> 
> (defmacro create-diff (xs)
>   `(progn ,@(reduce #'append
>     (mapcar #'(lambda (x)
>                `((shadow ',x)
>                  (defmethod ,x (a b)
>                    (,(SOMETHING-GOES-HERE x) a b))
>                  (defmethod ,x ((a symbol) b)
>                    `(,',x ,a ,b))
>                  (defmethod ,x (a (b symbol))
>                    `(,',x ,a ,b)))) xs))))
> 
> ...I've tried a few alternatives for SOMETHING-GOES-HERE, including
> 
> variations on "make-symbol", but something like...
> 
> (make-symbol (concatenate 'string "cl:" (format nil "~A" '+)))
> 
> ...results in "#:|cl:+|" which doesn't work.  So what's the right way
> 
> to get this working?
> 
> Thanks,
> 
> Greg Buchholz
> 

(find-symbol "+" "CL")

(find-symbol "ROUND" "CL")
From: Greg Buchholz
Subject: Re: concatenate symbols (token pasting)
Date: 
Message-ID: <1145401906.468747.7180@v46g2000cwv.googlegroups.com>
Rainer Joswig wrote:
> (find-symbol "+" "CL")

Works like a charm.  

Thanks,

Greg Buchholz
From: Pascal Bourguignon
Subject: Re: concatenate symbols (token pasting)
Date: 
Message-ID: <87k69miima.fsf@thalassa.informatimago.com>
"Greg Buchholz" <················@yahoo.com> writes:

>     I'm trying to overload some arithmetic functions, and I need a
> little help in writing a macro to help me out.  Instead of writing lots
> of boilerplate like...
>
> (shadow '+)
> (defmethod + (x y)
>   (cl:+ x y))
> (defmethod + ((x symbol) y)
>   `(+ ,x ,y))
> (defmethod + (x (y symbol))
>   `(+ ,x ,y))
>
> ...etc., I want to create a macro to help automate this.  I've tried
> several different things, and my latest attempt fails because I don't
> know how to concatenate symbols together.  That is, I want to create a
> fully qualified symbol like "cl:+" from a simple "+".  

You need to read about symbols and packages.  

If you don't like to read tutorial books (you don't seem to have read
Practical Common Lisp, have you?) you can have a look at Chapters 10
and 11 of CLHS.

http://www.lispworks.com/documentation/HyperSpec/Body/10_.htm
http://www.lispworks.com/documentation/HyperSpec/Body/11_.htm

Take note that every chapter of CLHS contains a "Concepts" section
that explains a lot.  You don't need to learn by heart the
"Dictionary" sections!




> Here's the
> current state of my macro...
>
> (defmacro create-diff (xs)
>   `(progn ,@(reduce #'append
>     (mapcar #'(lambda (x)
>                `((shadow ',x)
>                  (defmethod ,x (a b)
>                    (,(SOMETHING-GOES-HERE x) a b))
>                  (defmethod ,x ((a symbol) b)
>                    `(,',x ,a ,b))
>                  (defmethod ,x (a (b symbol))
>                    `(,',x ,a ,b)))) xs))))
>
> ...I've tried a few alternatives for SOMETHING-GOES-HERE, including
> variations on "make-symbol", but something like...
>
> (make-symbol (concatenate 'string "cl:" (format nil "~A" '+)))
>
> ...results in "#:|cl:+|" which doesn't work.  So what's the right way
> to get this working?

The argument to the macro can be a symbol in the CL package, or in the
current package.  If it never was shadowed, it'll be in CL, otherwise
it'll be the new symbol.  So you should take it as a symbol name
designator.  A symbol name is a string.

(defmacro create-diff (name)
   (let ((cl-symbol (or (find-symbol (string name) :common-lisp)
                        (error "~A  is not a symbol in COMMON-LISP" name)))
         (my-symbol (intern (string name) *package*)))
     `(progn
        (shadow ',cl-symbol)
        (print '(have fun with ,cl-symbol and ,my-symbol)))))


[21]> (create-diff "+")

(HAVE FUN WITH COMMON-LISP:+ AND +) 
(HAVE FUN WITH COMMON-LISP:+ AND +)
[22]> (create-diff :+)

(HAVE FUN WITH COMMON-LISP:+ AND +) 
(HAVE FUN WITH COMMON-LISP:+ AND +)
[23]> (create-diff cl::+)

(HAVE FUN WITH COMMON-LISP:+ AND +) 
(HAVE FUN WITH COMMON-LISP:+ AND +)
[24]> (create-diff +)

(HAVE FUN WITH COMMON-LISP:+ AND +) 
(HAVE FUN WITH COMMON-LISP:+ AND +)
[25]> 
         
-- 
__Pascal Bourguignon__                     http://www.informatimago.com/

NOTE: The most fundamental particles in this product are held
together by a "gluing" force about which little is currently known
and whose adhesive power can therefore not be permanently
guaranteed.
From: Greg Buchholz
Subject: Re: concatenate symbols (token pasting)
Date: 
Message-ID: <1145417061.670690.230720@u72g2000cwu.googlegroups.com>
Pascal Bourguignon wrote:
> You need to read about symbols and packages.
>
> If you don't like to read tutorial books (you don't seem to have read
> Practical Common Lisp, have you?)

Nope.  I've got a copy of Graham's ANSI_Common_Lisp.

>you can have a look at Chapters 10 and 11 of CLHS.
>
> http://www.lispworks.com/documentation/HyperSpec/Body/10_.htm
> http://www.lispworks.com/documentation/HyperSpec/Body/11_.htm
>
> Take note that every chapter of CLHS contains a "Concepts" section
> that explains a lot.

I'll take a look.  Thanks.  I thought I had a solution earlier, but
that apprarently depends on whether or not I've loaded other files, the
phases of the moon, etc.  For example, when I tried your snippet...

~/lisp$ cat pascal.lisp
(defmacro create-diff (name)
   (let ((cl-symbol (or (find-symbol (string name) :common-lisp)
                        (error "~A  is not a symbol in COMMON-LISP"
name)))
         (my-symbol (intern (string name) *package*)))
     `(progn
        (shadow ',cl-symbol)
        (print '(have fun with ,cl-symbol and ,my-symbol)))))

~/lisp$ lisp
CMU Common Lisp Snapshot 2005-03, running on greg
With core: /usr/local/lib/cmucl/lib/lisp.core
Dumped on: Tue, 2005-03-01 12:35:46-08:00 on lorien
See <http://www.cons.org/cmucl/> for support information.
Loaded subsystems:
    Python 1.1, target Intel x86
    CLOS based on Gerd's PCL 2004/04/14 03:32:47
* (load "pascal.lisp")

; Loading #P"/home/greg/lisp/pascal.lisp".
T
* (create-diff "+")

(HAVE FUN WITH COMMON-LISP:+ AND COMMON-LISP:+)
(HAVE FUN WITH COMMON-LISP:+ AND COMMON-LISP:+)
* (create-diff "+")

(HAVE FUN WITH COMMON-LISP:+ AND +)
(HAVE FUN WITH COMMON-LISP:+ AND +)

...the first time evaluating "create-diff" gives a different result
than the second invocation.  I'm assuming "shadow" is the culprit, but
it's not immediately obvious to me why I get two different answers.
And here's the latest thing I've tried,  but this doesn't work.
Neither loading from a file nor macroexpand-1 gives me any symbols with
a "COMMON-LISP:" prefix attached...

(defmacro create-diff (xs)
  `(progn ,@(reduce #'append
    (mapcar #'(lambda (x)
               (let ((cl-sym (find-symbol (string x) :common-lisp))
                     (my-sym (intern (string x) *package*)))
               `((shadow ',cl-sym)
                 (defmethod ,my-sym (a b)
                   (,cl-sym a b))
                 (defmethod ,my-sym ((a symbol) b)
                   `(,',my-sym ,a ,b))
                 (defmethod ,my-sym (a (b symbol))
                   `(,',my-sym ,a ,b))))) xs))))

(create-diff (+ - * /))

(defun foo ()
  (values (+ 1 2)
          (+ 'a 'b)
          (+ 1 'x)
          (* 2 'y)
          (/ 5.0 2.0)))

...but, being the newbie that I am, I'm probably missing something
obvious.

Thanks,

Greg Buchholz
From: Ari Johnson
Subject: Re: concatenate symbols (token pasting)
Date: 
Message-ID: <m2irp6fdho.fsf@hermes.theari.com>
"Greg Buchholz" <················@yahoo.com> writes:

> Pascal Bourguignon wrote:
>> You need to read about symbols and packages.

He's right. :)

> ...but, being the newbie that I am, I'm probably missing something
> obvious.

I think that the obvious thing you are missing is knowing which
package you are working with at any given time.  Try this at the REPL:
  *package*
From: Greg Buchholz
Subject: Re: concatenate symbols (token pasting)
Date: 
Message-ID: <1145469697.606705.263020@u72g2000cwu.googlegroups.com>
Ari Johnson wrote:
> I think that the obvious thing you are missing is knowing which
> package you are working with at any given time.  Try this at the REPL:
>   *package*

OK, I've been reading up on packages, but I must be extra dense today,
because I'm not seeing the light.  Maybe someone can hold my hand and
fix the code below, so when I type (load "foo.lisp") at the REPL, it'll
work...

(defpackage "SYM-ARITH" (:use "COMMON-LISP"))

(in-package sym-arith)

(defmacro create-diff (xs)
  `(progn ,@(reduce #'append
    (mapcar #'(lambda (x)
               (let ((cl-sym (find-symbol (string x) :common-lisp))
                     (my-sym (intern (string x) *package*)))
               `((shadow ',cl-sym)
                 (defmethod ,my-sym (a b)
                   (,cl-sym a b))
                 (defmethod ,my-sym ((a symbol) b)
                   `(,',my-sym ,a ,b))
                 (defmethod ,my-sym (a (b symbol))
                   `(,',my-sym ,a ,b))))) xs))))

(format t "~A~%" (macroexpand-1 '(create-diff (+))))
(create-diff (+))
(princ (+ 'abc 'def))

...on my system, the result of the macroexpand-1 looks like...

(PROGN
  (SHADOW '+)
  (DEFMETHOD + (A B)
    (+ A B))
  (DEFMETHOD + ((A SYMBOL) B)
    `(+ ,A ,B))
  (DEFMETHOD + (A (B SYMBOL))
    `(+ ,A ,B)))

...which of course doesn't work.

Thanks,

Greg Buchholz
From: Bill Atkins
Subject: Re: concatenate symbols (token pasting)
Date: 
Message-ID: <87irp58m8d.fsf@rpi.edu>
"Greg Buchholz" <················@yahoo.com> writes:

> Ari Johnson wrote:
>> I think that the obvious thing you are missing is knowing which
>> package you are working with at any given time.  Try this at the REPL:
>>   *package*
>
> OK, I've been reading up on packages, but I must be extra dense today,
> because I'm not seeing the light.  Maybe someone can hold my hand and
> fix the code below, so when I type (load "foo.lisp") at the REPL, it'll
> work...
>
> (defpackage "SYM-ARITH" (:use "COMMON-LISP"))
>
> (in-package sym-arith)
>
> (defmacro create-diff (xs)
>   `(progn ,@(reduce #'append
>     (mapcar #'(lambda (x)
>                (let ((cl-sym (find-symbol (string x) :common-lisp))
>                      (my-sym (intern (string x) *package*)))
>                `((shadow ',cl-sym)
>                  (defmethod ,my-sym (a b)
>                    (,cl-sym a b))
>                  (defmethod ,my-sym ((a symbol) b)
>                    `(,',my-sym ,a ,b))
>                  (defmethod ,my-sym (a (b symbol))
>                    `(,',my-sym ,a ,b))))) xs))))
>
> (format t "~A~%" (macroexpand-1 '(create-diff (+))))
> (create-diff (+))
> (princ (+ 'abc 'def))
>
> ...on my system, the result of the macroexpand-1 looks like...
>
> (PROGN
>   (SHADOW '+)
>   (DEFMETHOD + (A B)
>     (+ A B))
>   (DEFMETHOD + ((A SYMBOL) B)
>     `(+ ,A ,B))
>   (DEFMETHOD + (A (B SYMBOL))
>     `(+ ,A ,B)))
>
> ...which of course doesn't work.
>
> Thanks,
>
> Greg Buchholz

Well, your code for the second two methods backquotes its argument.
Try this:

 (defmacro create-diff (xs)
  `(progn ,@(reduce #'append
    (mapcar #'(lambda (x)
               (let ((cl-sym (find-symbol (string x) :common-lisp))
                     (my-sym (intern (string x) *package*)))
               `((shadow ',cl-sym)
                 (defmethod ,my-sym (a b)
                   (,cl-sym a b))
                 (defmethod ,my-sym ((a symbol) b)
                   (,my-sym a b))
                 (defmethod ,my-sym (a (b symbol))
                   (,my-sym a b)))))
                 xs))))


You don't want to put a comma before the a and the b since these
symbols have no value within the macro itself; they are the names of
the parameters in the defmethod forms your macro emits.

--
Bill
From: Pascal Bourguignon
Subject: Re: concatenate symbols (token pasting)
Date: 
Message-ID: <87zmihe7am.fsf@thalassa.informatimago.com>
"Greg Buchholz" <················@yahoo.com> writes:
> OK, I've been reading up on packages, but I must be extra dense today,
> because I'm not seeing the light.  Maybe someone can hold my hand and
> fix the code below, so when I type (load "foo.lisp") at the REPL, it'll
> work...

I already told you why: because you need to shadow the symbol at macro
expansion time in addition to run-time.

>                (let ((cl-sym (find-symbol (string x) :common-lisp))
                 (let* ((cl-sym (find-symbol (string x) :common-lisp))

>                      (my-sym (intern (string x) *package*)))
                        (my-sym (progn (shadow cl-sym)
                                       (intern (string x) *package*))))


-- 
__Pascal Bourguignon__                     http://www.informatimago.com/

Nobody can fix the economy.  Nobody can be trusted with their finger
on the button.  Nobody's perfect.  VOTE FOR NOBODY.
From: Greg Buchholz
Subject: Re: concatenate symbols (token pasting)
Date: 
Message-ID: <1145474567.611381.179380@i39g2000cwa.googlegroups.com>
Pascal Bourguignon wrote:
>
> I already told you why: because you need to shadow the symbol at macro
> expansion time in addition to run-time.

Shoot.  I *swear* I tried your second solution before and had it fail.
But I just now tried it again, and it works.  I must have screwed
somthing else up before.  Maybe I had loaded into a previously botched
image, or some such.  Anyway...

Thanks again,

Greg Buchholz
From: sross
Subject: Re: concatenate symbols (token pasting)
Date: 
Message-ID: <1145444807.948578.68130@g10g2000cwb.googlegroups.com>
You might want to give this a read, it's a very good explanation on the
workings of the common lisp package system.
http://www.flownet.com/gat/packages.pdf

Sean.
From: Pascal Bourguignon
Subject: Re: concatenate symbols (token pasting)
Date: 
Message-ID: <8764l6grly.fsf@thalassa.informatimago.com>
"Greg Buchholz" <················@yahoo.com> writes:
> * (create-diff "+")
>
> (HAVE FUN WITH COMMON-LISP:+ AND COMMON-LISP:+)
> (HAVE FUN WITH COMMON-LISP:+ AND COMMON-LISP:+)
> * (create-diff "+")
>
> (HAVE FUN WITH COMMON-LISP:+ AND +)
> (HAVE FUN WITH COMMON-LISP:+ AND +)
>
> ...the first time evaluating "create-diff" gives a different result
> than the second invocation.  I'm assuming "shadow" is the culprit, but
> it's not immediately obvious to me why I get two different answers.

Yes, indeed.  When INTERN is called, symbol has not been shadowed yet,
the first time.  So we need to shadow it at macro expansion time too.

(defmacro create-diff (name)
   (let* ((cl-symbol (or (find-symbol (string name) :common-lisp)
                         (error "~A  is not a symbol in COMMON-LISP" 
                                name)))
          (my-symbol (progn (shadow cl-symbol) 
                            (intern (string name) *package*))))
     `(progn
        (shadow ',cl-symbol)
        (print '(have fun with ,cl-symbol and ,my-symbol)))))



-- 
__Pascal Bourguignon__                     http://www.informatimago.com/

CAUTION: The mass of this product contains the energy equivalent of
85 million tons of TNT per net ounce of weight.
From: Thomas A. Russ
Subject: Re: concatenate symbols (token pasting)
Date: 
Message-ID: <ymiodyxwfrq.fsf@sevak.isi.edu>
"Greg Buchholz" <················@yahoo.com> writes:

>     I'm trying to overload some arithmetic functions, and I need a
> little help in writing a macro to help me out.  Instead of writing lots
> of boilerplate like...
> 
> (shadow '+)
> (defmethod + (x y)
>   (cl:+ x y))
> (defmethod + ((x symbol) y)
>   `(+ ,x ,y))
> (defmethod + (x (y symbol))
>   `(+ ,x ,y))
> 
> ...etc., I want to create a macro to help automate this.  I've tried
> several different things, and my latest attempt fails because I don't
> know how to concatenate symbols together.  That is, I want to create a
> fully qualified symbol like "cl:+" from a simple "+".  Here's the
> current state of my macro...
> 
> (defmacro create-diff (xs)
>   `(progn ,@(reduce #'append
>     (mapcar #'(lambda (x)
>                `((shadow ',x)
>                  (defmethod ,x (a b)
>                    (,(SOMETHING-GOES-HERE x) a b))
>                  (defmethod ,x ((a symbol) b)
>                    `(,',x ,a ,b))
>                  (defmethod ,x (a (b symbol))
>                    `(,',x ,a ,b)))) xs))))
> 
> ...I've tried a few alternatives for SOMETHING-GOES-HERE, including
> variations on "make-symbol", but something like...
> 
> (make-symbol (concatenate 'string "cl:" (format nil "~A" '+)))

You want either INTERN or FIND-SYMBOL, specifying the package.

> ...results in "#:|cl:+|" which doesn't work.  So what's the right way
> to get this working?

Also, instead of (REDUCE (APPEND (MAPCAR ...)))
you should look at (MAPCAN ...) instead.

But you will also need to do a lot more sophisticated management of
symbols and packages to get this to work.  The reason is that by the
time macroexpansion happens, the reader has already read an interned the
symbols in your code.  The call to SHADOW will change future reading of
the symbol, but it won't affect the symbol that has already been read
before the macro expands.

It would seem you would also need to do the shadowing as part of the
macro expansion code as well as emitting it in the expansion.  This is
likely to get a bit tricky, but it should be doable.

Here's a sketch of how one might make such a macro.  This just operates
on a single symbol, but you can generalize it to take a list of
operators instead.

(defmacro create-diff (operator)
  ;;; OPERATOR is (potentially) read before changes to the package
  ;;;   structure caused by shadowing, so this macro is careful to
  ;;;   build the symbols it wants from symbol-names.

  ;; First, make sure this symbol-name isshadowed in the current package.
  (shadow operator)

  ;; Second, create and find the symbols we need.
  (let ((my-operator (intern (symbol-name operator)))  ; Current package
        (cl-operator (find-symbol (symbol-name operator) "CL")))
     (unless cl-operator
        (error "Can't find common-lisp symbol for " operator))
     `(progn
        (shadow ',operator)
        (defmethod ,my-operator (a b)
           (,cl-operator a b))
        (defmethod ,my-operator ((a symbol) b)
            ;; Not sure if you want MY-OPERATOR or CL-OPERATOR here:
            `(,',my-operator ,a ,b))
        (defmethod ,my-operator (a (b symbol))
            ;; Not sure if you want MY-OPERATOR or CL-OPERATOR here:
            `(,',my-operator ,a ,b)))))

Simple testing indicates that it works:

USER> (defpackage "FOO")
#<The FOO package>
USER> (in-package "FOO")
#<The FOO package>
FOO> (create-diff +)
#<STANDARD-METHOD + (T SYMBOL)>
FOO> (+ 3 4)
7
FOO> (+ 3 'b)
(+ 3 B)
FOO> (+ 'a 5)
(+ A 5)



-- 
Thomas A. Russ,  USC/Information Sciences Institute
From: Greg Buchholz
Subject: Re: concatenate symbols (token pasting)
Date: 
Message-ID: <1145489181.772768.209190@j33g2000cwa.googlegroups.com>
Thomas A. Russ wrote:
> But you will also need to do a lot more sophisticated management of
> symbols and packages to get this to work.  The reason is that by the
> time macroexpansion happens, the reader has already read an interned the
> symbols in your code.  The call to SHADOW will change future reading of
> the symbol, but it won't affect the symbol that has already been read
> before the macro expands.
>
> It would seem you would also need to do the shadowing as part of the
> macro expansion code as well as emitting it in the expansion.  This is
> likely to get a bit tricky, but it should be doable.

*Click*.  Thanks for your explaination, I think I understand it now.

Greg Buchholz