From: Anton V. Belyaev
Subject: How to create symbols for macro with exact names?
Date: 
Message-ID: <1150834224.921522.46810@y41g2000cwy.googlegroups.com>
>From the following piece of code it should be evident what I am trying
to do.

(defmacro macro1 (param)
  `(let ((,(intern "var1") 777))
     ,param))
(macro1 var1)

I tried also

(defmacro macro1 (param)
  `(let ((,(make-symbol "var1") 777))
     ,param))
(macro1 var1)

Is it possible at all?
Thanks in advance.

From: ············@gmail.com
Subject: Re: How to create symbols for macro with exact names?
Date: 
Message-ID: <1150835612.094019.93400@g10g2000cwb.googlegroups.com>
Anton V. Belyaev wrote:
> >From the following piece of code it should be evident what I am trying
> to do.
>
> (defmacro macro1 (param)
>   `(let ((,(intern "var1") 777))
>      ,param))
> (macro1 var1)
>
> I tried also
>
> (defmacro macro1 (param)
>   `(let ((,(make-symbol "var1") 777))
>      ,param))
> (macro1 var1)
>
> Is it possible at all?
> Thanks in advance.

Do you expect (macro1 var1) to return 777?
It looks like you're trying to do this:

(defmacro macro1 (param)
`(let ((var1 777)) 
,param))
From: Deon Garrett
Subject: Re: How to create symbols for macro with exact names?
Date: 
Message-ID: <87irmv36rm.fsf@bender.deong.info>
"Anton V. Belyaev" <·············@gmail.com> writes:

>>From the following piece of code it should be evident what I am trying
> to do.
>
> (defmacro macro1 (param)
>   `(let ((,(intern "var1") 777))
>      ,param))
> (macro1 var1)
>
> Is it possible at all?
> Thanks in advance.

You might want to explain your overall goal, as what you want to do is not
terribly common, but in the spirit of enough rope...

The problem with (intern "var1") is that the reader ordinarily upcases
everything it sees, but you're short circuiting that behavior.  So what
your (macro1 var1) actually expands to is

CL-USER> (macroexpand-1 '(macro1 var1))
(LET ((|var1| 777))
  VAR1)

but VAR1 and |var1| are different symbols (technically the pipes aren't
part of the symbol name, but we're close enough).  You can solve your
problem by uppercasing the string before you call intern.

(defmacro macro3 (param)
  `(let ((,(intern (string-upcase "var1")) 777))
     ,param))

But I still don't know what you actually hope to accomplish.  My version
macroexpands as follows.

CL-USER> (macroexpand-1 '(macro3 var1))
(LET ((VAR1 777))
  VAR1)

which is all well, but only works for argument "var1"

CL-USER> (macroexpand-1 '(macro3 var2))
(LET ((VAR1 777))
  VAR2)

and of course, VAR2 is unbound.  Which leads me to believe you might have
intended something like

(defmacro macro4 (param)
  `(let ((,param 777))
     ,param))

which at least works for any argument.  If you explain your problem,
someone here will almost certainly provide you with better advice than you
can get from the likes of me.  :)

-- 
Deon Garrett
Department of Computer Science
Institute for Intelligent Systems
The University of Memphis
·····@acm.org
From: Anton V. Belyaev
Subject: Re: How to create symbols for macro with exact names?
Date: 
Message-ID: <1150869285.492930.240750@p79g2000cwp.googlegroups.com>
Thank Deon!

My problem explanation was fuzzy, but you guessed in one of you
solutions
what was really needed :)

This is what I needed:

(defmacro macro3 (param)
  `(let ((,(intern (string-upcase "var1")) 777))
     ,param))
From: Pascal Bourguignon
Subject: Re: How to create symbols for macro with exact names?
Date: 
Message-ID: <87fyhzcu1d.fsf@thalassa.informatimago.com>
"Anton V. Belyaev" <·············@gmail.com> writes:

>>From the following piece of code it should be evident what I am trying
> to do.
>
> (defmacro macro1 (param)
>   `(let ((,(intern "var1") 777))
>      ,param))
> (macro1 var1)


[2]> (macroexpand '(macro1 var1))
(LET ((|var1| 777)) VAR1) ;
T

> I tried also
>
> (defmacro macro1 (param)
>   `(let ((,(make-symbol "var1") 777))
>      ,param))
> (macro1 var1)
>
> Is it possible at all?

Yes.
Read about READTABLE-CASE in CLHS.



A generic solution could be (it really depends on what you want):

(eval-when (:compile-toplevel :load-toplevel :execute)
  (defun string-invert (string &key (start 0) (end nil))
     (map 'string (lambda (ch)
                     (cond ((char= (char-upcase   ch) ch) (char-downcase ch))
                           ((char= (char-downcase ch) ch) (char-upcase   ch))
                           (t ch))) (subseq string start end))))


[12]> (defmacro macro1 (param)
  `(let ((,(intern 
             (funcall
                (ecase (readtable-case *readtable*)
                  (:upcase   (function string-upcase))
                  (:downcase (function string-downcase))
                  (:invert   (function string-invert))
                  (:preserve (function identity)))
                "var1")) 777))
     ,param))

MACRO1
[13]> (macroexpand '(macro1 var1))
(LET ((VAR1 777)) VAR1) ;
T
[14]> (|SETF| (|READTABLE-CASE| |*READTABLE*|) :|DOWNCASE|)
:|DOWNCASE|
[15]> (|MACROEXPAND| '(|MACRO1| VAR1))
(|LET| ((VAR1 777)) VAR1) ;
|T|
[16]> (|SETF| (|READTABLE-CASE| |*READTABLE*|) :|INVERT|)
:invert
[17]> (|MACROEXPAND| '(|MACRO1| var1))
(let ((var1 777)) var1) ;
t
[18]> (|SETF| (|READTABLE-CASE| |*READTABLE*|) :|PRESERVE|)
:PRESERVE
[19]> (|MACROEXPAND| '(|MACRO1| var1))
(LET ((var1 777)) var1) ;
T
[20]> 

This is for interactive use, but on the other hand, when you use the
macro in the sources of a program, the symbol given to the macro will
be read by the same readtable as the macro itself, so it may be better
to write:

(defmacro macro1 (param)
  `(let ((,(intern 
             #.(funcall
                (ecase (readtable-case *readtable*)
                  (:upcase   (function string-upcase))
                  (:downcase (function string-downcase))
                  (:invert   (function string-invert))
                  (:preserve (function identity)))
                "var1")) 777))
     ,param))


Or you could just consider that your sources will use the :UPCASE
(which is the default) readtable-case, and just write:

(defmacro macro1 (param)
  `(let ((,(intern (string-upcase "var1")) 777))
     ,param))

Or just:

(defmacro macro1 (param)
  `(let ((,(intern (string-upcase "VAR1")) 777))
     ,param))

But then of course, people who like to use a :modern or :invert
readtable-case will have difficulty using it.  You can't make
everybody happy all the time.


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

HEALTH WARNING: Care should be taken when lifting this product,
since its mass, and thus its weight, is dependent on its velocity
relative to the user.
From: Anton V. Belyaev
Subject: Re: How to create symbols for macro with exact names?
Date: 
Message-ID: <1150869811.158839.153230@i40g2000cwc.googlegroups.com>
Thank you very much, Pascal!

I appreciate your detailed explanation of readtable case.
So I can make my solution even more generic!
From: Thomas A. Russ
Subject: Re: How to create symbols for macro with exact names?
Date: 
Message-ID: <ymifyhr5xsc.fsf@sevak.isi.edu>
Pascal Bourguignon <···@informatimago.com> writes:

> Marcin 'Qrczak' Kowalczyk <······@knm.org.pl> writes:
> 
> > Pascal Bourguignon <···@informatimago.com> writes:
> >
> >>   (defun string-invert (string &key (start 0) (end nil))
> >>      (map 'string (lambda (ch)
> >>                      (cond ((char= (char-upcase   ch) ch) (char-downcase ch))
> >>                            ((char= (char-downcase ch) ch) (char-upcase   ch))
> >>                            (t ch))) (subseq string start end))))
> >
> > Case should not be inverted if the string contains both uppercase and
> > lowercase letters.
> 
> Indeed. s/string-invert/symbol-name-readtable-case-invert/
> 
>   (defun symbol-name-readtable-case-invert (symbol-name)
>      (cond ((every (lambda (ch) (char/= ch (char-downcase ch))) symbol-name)
>             (string-downcase symbol-name))
>            ((every (lambda (ch) (char/= ch (char-upcase   ch))) symbol-name)
>             (string-upcase symbol-name))
>            (t symbol-name)))
> 
> (mapcar
>     (function symbol-name-readtable-case-invert)
>    '("abc" "ABC" "Abc" "abC"))
> --> ("ABC" "abc" "Abc" "abC")

I don't think this one is correct either.  Consider:

(symbol-name-readtable-case-invert "abc")    ==>  "ABC"      Correct
(symbol-name-readtable-case-invert "abc-87") ==>  "abc-87"   ERROR!
(symbol-name-readtable-case-invert "A-87")   ==>  "A-87"     ERROR!

The correct algorithm actually needs to really be multi-pass.
A simple one would be like this, although I find it more efficient
to use an iteration and do both tests in a single pass through
the loop

Solution 1:

(defun symbol-name-readtable-case-invert (symbol-name)
  (let ((lower-case-char-seen (some #'lower-case-p symbol-name))
        (upper-case-char-seen (some #'upper-case-p symbol-name)))
    (if lower-case-char-seen
        (if upper-case-char-seen
            symbol-name
            (string-upcase symbol-name))
        (if upper-case-char-seen
            (string-downcase symbol-name)
            symbol-name))))

Solution 2:
(defun symbol-name-readtable-case-invert (symbol-name)
  (let ((lower-case-char-seen nil)
        (upper-case-char-seen nil))
    (loop for ch across symbol-name
          when (lower-case-p ch) do (setq lower-case-seen t)
          when (upper-case-p ch) do (setq upper-case-seen t))
    (if lower-case-char-seen
        (if upper-case-char-seen
            symbol-name
            (string-upcase symbol-name))
        (if upper-case-char-seen
            (string-downcase symbol-name)
            symbol-name))))


-- 
Thomas A. Russ,  USC/Information Sciences Institute