From: Jeff
Subject: Interning keywords from strings
Date: 
Message-ID: <1126194104.401661.31480@g43g2000cwa.googlegroups.com>
Is there a way to intern a keyword from a string without getting the
'|' characters?

CL-USER> (intern "abc" :keyword)
:|abc|
:EXTERNAL

whereas

CL-USER> (intern (format nil "~a" :abc) :keyword)
:ABC
:EXTERNAL

I'm trying to mix the two:

CL-USER> (intern (format nil "~a-~a" "key" :abc) :keyword)
:|key-ABC|
:EXTERNAL

--jeff

From: JP Massar
Subject: Re: Interning keywords from strings
Date: 
Message-ID: <fdp0i1ptc85i05cahdvqgihk0mkq9aop0o@4ax.com>
On 8 Sep 2005 08:41:44 -0700, "Jeff" <····················@boeing.com>
wrote:

>Is there a way to intern a keyword from a string without getting the
>'|' characters?

 :|abc| is the symbol in the keyword package whose
characters are lowercase a b c.  (See below)

The '|' characters aren't "really" there.  They are just printed  by
the printer so that the symbol, whose  characters are lowercase a b c,
can be reread, and so that you, the reader, know that the characters
are lowercase.

See the discussion of the printer and the reader and standard case
conversion  in the Hyperspec.

>
>CL-USER> (intern "abc" :keyword)
>:|abc|
>:EXTERNAL


(intern (string-upcase "abc") :keyword)

>
>whereas
>
>CL-USER> (intern (format nil "~a" :abc) :keyword)
>:ABC
>:EXTERNAL

Because :abc is really the symbol whose characters are uppercase A B C
>
>I'm trying to mix the two:
>
>CL-USER> (intern (format nil "~a-~a" "key" :abc) :keyword)
>:|key-ABC|
>:EXTERNAL
>
>--jeff
From: Thomas A. Russ
Subject: Re: Interning keywords from strings
Date: 
Message-ID: <ymiek7zdz12.fsf@sevak.isi.edu>
"Jeff" <····················@boeing.com> writes:

> I'm trying to mix the two:
> 
> CL-USER> (intern (format nil "~a-~a" "key" :abc) :keyword)
> :|key-ABC|
> :EXTERNAL

At the risk of getting in trouble for not properly handling situations
where someone sets READTABLE-CASE to something other than UPCASE, you
can do the following:

  (intern (format nil ··@:(~a-~a~)" "key" :abc) :keyword)

which you can nicely generalize via format hackery to

  (defun create-keyword (&rest components)
      (intern (format nil ··@:(~{~a~^-~}~)" components) :keyword))

If you want to have a simple solution that respects READTABLE-CASE
settings, then you can always use READ-FROM-STRING instead of INTERN:

   (read-from-string (format nil "~a-~a" "key" :abc) :keyword)

but this then opens other cans of worms with regard to inputs that need
escaping to be symbol constituents, worrying about the setting of
*READ-EVAL*, etc.

That leaves writing your own handler for the current state of
READTABLE-CASE.  But this brings up a missing built-in function in
Common Lisp.  There is no standard function to do the STRING-INVERT
operation from the reader.  It is something that you will need to write
on your own.

(defun frob-symbol-name-according-to-readcase (name)
  (case (readtable-case *readtable*)
     (:upcase (upcase-string name))
     (:downcase (downcase-string name))
     (:preserve name)
     (:invert (if (some #'upper-case-p name)
	          (if (some #'lower-case-p name)
                      name                         ; Mixed case => preserve
                      (string-downcase name))      ; No lower case letters
                  (string-upcase name)))))         ; No upper case letters

I think I got the :invert case correct....

You can then call (intern (frob-symbol-name-according-to-readcase name) :keyword)
and get the behavior you are seeking.

-- 
Thomas A. Russ,  USC/Information Sciences Institute
From: Patrick Frankenberger
Subject: Re: Interning keywords from strings
Date: 
Message-ID: <dfpo31$m8k$03$1@news.t-online.com>
Jeff wrote:
> Is there a way to intern a keyword from a string without getting the
> '|' characters?
> 
> CL-USER> (intern "abc" :keyword)
> :|abc|
> :EXTERNAL

Easy:

CL-USER> (intern "ABC" :keyword)
:ABC

HTH,
Patrick
From: Alan Crowe
Subject: Re: Interning keywords from strings
Date: 
Message-ID: <86ll271npq.fsf@cawtech.freeserve.co.uk>
Jeff asks
> Is there a way to intern a keyword from a string without getting the
> '|' characters?
>
> CL-USER> (intern "abc" :keyword)
> :|abc|
> :EXTERNAL

The secret is in the print-escape. Try

(let ((key (intern "abc" :keyword)))
    (dolist (flag '(t nil) (symbol-name key))
      (write key :escape flag)
      (terpri)))
:|abc|
abc
"abc"

You are creating a symbol whose name is the three lower case
characters a,b,c.

The vertical lines are escape characters put there by the
printer in anticipation of you trying to read the character
back in using the current readtable.

Try

* (setf (readtable-case *readtable*) :preserve)

* (INTERN "abc" :KEYWORD)

:abc
:EXTERNAL

The vertical lines have gone, because they were in a sense,
never there. Since the readtable at the time of printing
preserves case, the printer in the ReadEvalPrintLoop is
happy to write out the symbol name without escape characters
to protect it from being upcased when it is read back in.

Alan Crowe
Edinburgh
Scotland

PS you will need (SETF (READTABLE-CASE *READTABLE*) :UPCASE)
to get back to normal.
From: Jeff
Subject: Re: Interning keywords from strings
Date: 
Message-ID: <1126201173.325126.190640@o13g2000cwo.googlegroups.com>
Thank you all for the explanations. It all makes sense now. The case
preservation technique is well worth knowing. In the case at hand
there's no requirement for lower case, so I'll probably just change it
to upper.

-jeff
From: joesb
Subject: Re: Interning keywords from strings
Date: 
Message-ID: <1126201397.913414.316640@f14g2000cwb.googlegroups.com>
Regarding case sensitive lisp, How would this work out?
From: Peter Seibel
Subject: Re: Interning keywords from strings
Date: 
Message-ID: <m24q8v6xjt.fsf@gigamonkeys.com>
"joesb" <··········@gmail.com> writes:

> Regarding case sensitive lisp, How would this work out?

Common Lisp is already case sensitive. (That's in fact the issue here:
the symbol whose name is "abc" is different than the symbol whose name
is "ABC".) However--and this is the bit that causes folks to
misidentify Lisp as case insensitive--the reader (in the default
setting) smashes the case of unescaped letters in symbols to upper
case. I.e. it's not that the reader ignores differences in case (which
would be case-insensitive) but that it normalizes symbol names to a
particular case (upper).

-Peter

-- 
Peter Seibel           * ·····@gigamonkeys.com
Gigamonkeys Consulting * http://www.gigamonkeys.com/
Practical Common Lisp  * http://www.gigamonkeys.com/book/