Common Lisp add suffix to symbol for use in macros





.everyoneloves__top-leaderboard:empty,.everyoneloves__mid-leaderboard:empty,.everyoneloves__bot-mid-leaderboard:empty{ height:90px;width:728px;box-sizing:border-box;
}







1















How do you introduce new, predictably named identifiers with suffixes in a macro?





So, I'm writing a simple library for manipulating quaternions. I'm using the simplest representation that could possibly work, a list of components, for the time being, but I'd like to define a simple API that doesn't depend on that representation.



When defining algorithms, I want to refer to each of the components of the quaternion with a predictable name like somesymbol-realpart or somesymbol-i.



I'd like to be able to get the following snippet to work.



(let
((my-quat '(1 2 3 4)))
(with-quaternion my-quat
(assert-equalp 1 my-quat-realpart)
(assert-equalp 2 my-quat-i)
(assert-equalp 3 my-quat-j)
(assert-equalp 4 my-quat-k)))


However, the method I used for producing a symbol with a suffix seems to produce strange case-sensitive symbols with escaped uppercase characters.



(defun add-suffix-to-symbol (sym suffix)
(intern (concatenate 'string "" (string sym) "-" suffix)))


As a result of converting a symbol to a string, it is printed in uppercase... which is a totally valid canonicalization. However, creating a new symbol via intern preserves the case for some reason, so I have to do something like the following to refer to bindings introduced by with-quaternion.



(let
((my-quat '(1 2 3 4)))
(with-quaternion my-quat
(assert-equalp 1 |MY-QUAT-realpart|)
(assert-equalp 2 |MY-QUAT-i|)
(assert-equalp 3 |MY-QUAT-j|)
(assert-equalp 4 |MY-QUAT-k|)))


How do I create a new symbol that's identical to an old one but with a suffix so that it can be used in a macro?



for reference, here is all the code.



(defun assert-equalp (e a)
(assert (equalp e a)))

(defun quat-realpart (q)
(first q))

(defun quat-i (q)
(second q))

(defun quat-j (q)
(third q))

(defun quat-k (q)
(fourth q))

(assert-equalp '1 (quat-realpart '(1 2 3 4)))
(assert-equalp '2 (quat-i '(1 2 3 4)))
(assert-equalp '3 (quat-j '(1 2 3 4)))
(assert-equalp '4 (quat-k '(1 2 3 4)))

(defun add-suffix-to-symbol (sym suffix)
(intern (concatenate 'string "" (string sym) "-" suffix)))

(print (add-suffix-to-symbol 'a "suffix"))

(defgeneric with-quaternion-impl (q-sym body))

(defmethod with-quaternion-impl ((q-sym symbol) body)
(let
((q-realpart (add-suffix-to-symbol q-sym "realpart"))
(q-i (add-suffix-to-symbol q-sym "i"))
(q-j (add-suffix-to-symbol q-sym "j"))
(q-k (add-suffix-to-symbol q-sym "k")))
`(let
((,q-realpart (quat-realpart ,q-sym))
(,q-i (quat-i ,q-sym))
(,q-j (quat-j ,q-sym))
(,q-k (quat-k ,q-sym)))
(progn ,@body))))


(defmacro with-quaternion (q-sym &rest body)
(with-quaternion-impl q-sym body))


(let
((my-quat '(1 2 3 4)))
(with-quaternion my-quat
(assert-equalp 1 |MY-QUAT-realpart|)
(assert-equalp 2 |MY-QUAT-i|)
(assert-equalp 3 |MY-QUAT-j|)
(assert-equalp 4 |MY-QUAT-k|)))

(let
((my-quat '(1 2 3 4)))
(with-quaternion my-quat
(assert-equalp 1 my-quat-realpart)
(assert-equalp 2 my-quat-i)
(assert-equalp 3 my-quat-j)
(assert-equalp 4 my-quat-k)))


When run under clisp, it prints the following symbol, clearly with escaped uppercase characters.



|A-suffix|


and produces the following error message:



*** - PROGN: variable MY-QUAT-REALPART has no value









share|improve this question





























    1















    How do you introduce new, predictably named identifiers with suffixes in a macro?





    So, I'm writing a simple library for manipulating quaternions. I'm using the simplest representation that could possibly work, a list of components, for the time being, but I'd like to define a simple API that doesn't depend on that representation.



    When defining algorithms, I want to refer to each of the components of the quaternion with a predictable name like somesymbol-realpart or somesymbol-i.



    I'd like to be able to get the following snippet to work.



    (let
    ((my-quat '(1 2 3 4)))
    (with-quaternion my-quat
    (assert-equalp 1 my-quat-realpart)
    (assert-equalp 2 my-quat-i)
    (assert-equalp 3 my-quat-j)
    (assert-equalp 4 my-quat-k)))


    However, the method I used for producing a symbol with a suffix seems to produce strange case-sensitive symbols with escaped uppercase characters.



    (defun add-suffix-to-symbol (sym suffix)
    (intern (concatenate 'string "" (string sym) "-" suffix)))


    As a result of converting a symbol to a string, it is printed in uppercase... which is a totally valid canonicalization. However, creating a new symbol via intern preserves the case for some reason, so I have to do something like the following to refer to bindings introduced by with-quaternion.



    (let
    ((my-quat '(1 2 3 4)))
    (with-quaternion my-quat
    (assert-equalp 1 |MY-QUAT-realpart|)
    (assert-equalp 2 |MY-QUAT-i|)
    (assert-equalp 3 |MY-QUAT-j|)
    (assert-equalp 4 |MY-QUAT-k|)))


    How do I create a new symbol that's identical to an old one but with a suffix so that it can be used in a macro?



    for reference, here is all the code.



    (defun assert-equalp (e a)
    (assert (equalp e a)))

    (defun quat-realpart (q)
    (first q))

    (defun quat-i (q)
    (second q))

    (defun quat-j (q)
    (third q))

    (defun quat-k (q)
    (fourth q))

    (assert-equalp '1 (quat-realpart '(1 2 3 4)))
    (assert-equalp '2 (quat-i '(1 2 3 4)))
    (assert-equalp '3 (quat-j '(1 2 3 4)))
    (assert-equalp '4 (quat-k '(1 2 3 4)))

    (defun add-suffix-to-symbol (sym suffix)
    (intern (concatenate 'string "" (string sym) "-" suffix)))

    (print (add-suffix-to-symbol 'a "suffix"))

    (defgeneric with-quaternion-impl (q-sym body))

    (defmethod with-quaternion-impl ((q-sym symbol) body)
    (let
    ((q-realpart (add-suffix-to-symbol q-sym "realpart"))
    (q-i (add-suffix-to-symbol q-sym "i"))
    (q-j (add-suffix-to-symbol q-sym "j"))
    (q-k (add-suffix-to-symbol q-sym "k")))
    `(let
    ((,q-realpart (quat-realpart ,q-sym))
    (,q-i (quat-i ,q-sym))
    (,q-j (quat-j ,q-sym))
    (,q-k (quat-k ,q-sym)))
    (progn ,@body))))


    (defmacro with-quaternion (q-sym &rest body)
    (with-quaternion-impl q-sym body))


    (let
    ((my-quat '(1 2 3 4)))
    (with-quaternion my-quat
    (assert-equalp 1 |MY-QUAT-realpart|)
    (assert-equalp 2 |MY-QUAT-i|)
    (assert-equalp 3 |MY-QUAT-j|)
    (assert-equalp 4 |MY-QUAT-k|)))

    (let
    ((my-quat '(1 2 3 4)))
    (with-quaternion my-quat
    (assert-equalp 1 my-quat-realpart)
    (assert-equalp 2 my-quat-i)
    (assert-equalp 3 my-quat-j)
    (assert-equalp 4 my-quat-k)))


    When run under clisp, it prints the following symbol, clearly with escaped uppercase characters.



    |A-suffix|


    and produces the following error message:



    *** - PROGN: variable MY-QUAT-REALPART has no value









    share|improve this question

























      1












      1








      1


      1






      How do you introduce new, predictably named identifiers with suffixes in a macro?





      So, I'm writing a simple library for manipulating quaternions. I'm using the simplest representation that could possibly work, a list of components, for the time being, but I'd like to define a simple API that doesn't depend on that representation.



      When defining algorithms, I want to refer to each of the components of the quaternion with a predictable name like somesymbol-realpart or somesymbol-i.



      I'd like to be able to get the following snippet to work.



      (let
      ((my-quat '(1 2 3 4)))
      (with-quaternion my-quat
      (assert-equalp 1 my-quat-realpart)
      (assert-equalp 2 my-quat-i)
      (assert-equalp 3 my-quat-j)
      (assert-equalp 4 my-quat-k)))


      However, the method I used for producing a symbol with a suffix seems to produce strange case-sensitive symbols with escaped uppercase characters.



      (defun add-suffix-to-symbol (sym suffix)
      (intern (concatenate 'string "" (string sym) "-" suffix)))


      As a result of converting a symbol to a string, it is printed in uppercase... which is a totally valid canonicalization. However, creating a new symbol via intern preserves the case for some reason, so I have to do something like the following to refer to bindings introduced by with-quaternion.



      (let
      ((my-quat '(1 2 3 4)))
      (with-quaternion my-quat
      (assert-equalp 1 |MY-QUAT-realpart|)
      (assert-equalp 2 |MY-QUAT-i|)
      (assert-equalp 3 |MY-QUAT-j|)
      (assert-equalp 4 |MY-QUAT-k|)))


      How do I create a new symbol that's identical to an old one but with a suffix so that it can be used in a macro?



      for reference, here is all the code.



      (defun assert-equalp (e a)
      (assert (equalp e a)))

      (defun quat-realpart (q)
      (first q))

      (defun quat-i (q)
      (second q))

      (defun quat-j (q)
      (third q))

      (defun quat-k (q)
      (fourth q))

      (assert-equalp '1 (quat-realpart '(1 2 3 4)))
      (assert-equalp '2 (quat-i '(1 2 3 4)))
      (assert-equalp '3 (quat-j '(1 2 3 4)))
      (assert-equalp '4 (quat-k '(1 2 3 4)))

      (defun add-suffix-to-symbol (sym suffix)
      (intern (concatenate 'string "" (string sym) "-" suffix)))

      (print (add-suffix-to-symbol 'a "suffix"))

      (defgeneric with-quaternion-impl (q-sym body))

      (defmethod with-quaternion-impl ((q-sym symbol) body)
      (let
      ((q-realpart (add-suffix-to-symbol q-sym "realpart"))
      (q-i (add-suffix-to-symbol q-sym "i"))
      (q-j (add-suffix-to-symbol q-sym "j"))
      (q-k (add-suffix-to-symbol q-sym "k")))
      `(let
      ((,q-realpart (quat-realpart ,q-sym))
      (,q-i (quat-i ,q-sym))
      (,q-j (quat-j ,q-sym))
      (,q-k (quat-k ,q-sym)))
      (progn ,@body))))


      (defmacro with-quaternion (q-sym &rest body)
      (with-quaternion-impl q-sym body))


      (let
      ((my-quat '(1 2 3 4)))
      (with-quaternion my-quat
      (assert-equalp 1 |MY-QUAT-realpart|)
      (assert-equalp 2 |MY-QUAT-i|)
      (assert-equalp 3 |MY-QUAT-j|)
      (assert-equalp 4 |MY-QUAT-k|)))

      (let
      ((my-quat '(1 2 3 4)))
      (with-quaternion my-quat
      (assert-equalp 1 my-quat-realpart)
      (assert-equalp 2 my-quat-i)
      (assert-equalp 3 my-quat-j)
      (assert-equalp 4 my-quat-k)))


      When run under clisp, it prints the following symbol, clearly with escaped uppercase characters.



      |A-suffix|


      and produces the following error message:



      *** - PROGN: variable MY-QUAT-REALPART has no value









      share|improve this question














      How do you introduce new, predictably named identifiers with suffixes in a macro?





      So, I'm writing a simple library for manipulating quaternions. I'm using the simplest representation that could possibly work, a list of components, for the time being, but I'd like to define a simple API that doesn't depend on that representation.



      When defining algorithms, I want to refer to each of the components of the quaternion with a predictable name like somesymbol-realpart or somesymbol-i.



      I'd like to be able to get the following snippet to work.



      (let
      ((my-quat '(1 2 3 4)))
      (with-quaternion my-quat
      (assert-equalp 1 my-quat-realpart)
      (assert-equalp 2 my-quat-i)
      (assert-equalp 3 my-quat-j)
      (assert-equalp 4 my-quat-k)))


      However, the method I used for producing a symbol with a suffix seems to produce strange case-sensitive symbols with escaped uppercase characters.



      (defun add-suffix-to-symbol (sym suffix)
      (intern (concatenate 'string "" (string sym) "-" suffix)))


      As a result of converting a symbol to a string, it is printed in uppercase... which is a totally valid canonicalization. However, creating a new symbol via intern preserves the case for some reason, so I have to do something like the following to refer to bindings introduced by with-quaternion.



      (let
      ((my-quat '(1 2 3 4)))
      (with-quaternion my-quat
      (assert-equalp 1 |MY-QUAT-realpart|)
      (assert-equalp 2 |MY-QUAT-i|)
      (assert-equalp 3 |MY-QUAT-j|)
      (assert-equalp 4 |MY-QUAT-k|)))


      How do I create a new symbol that's identical to an old one but with a suffix so that it can be used in a macro?



      for reference, here is all the code.



      (defun assert-equalp (e a)
      (assert (equalp e a)))

      (defun quat-realpart (q)
      (first q))

      (defun quat-i (q)
      (second q))

      (defun quat-j (q)
      (third q))

      (defun quat-k (q)
      (fourth q))

      (assert-equalp '1 (quat-realpart '(1 2 3 4)))
      (assert-equalp '2 (quat-i '(1 2 3 4)))
      (assert-equalp '3 (quat-j '(1 2 3 4)))
      (assert-equalp '4 (quat-k '(1 2 3 4)))

      (defun add-suffix-to-symbol (sym suffix)
      (intern (concatenate 'string "" (string sym) "-" suffix)))

      (print (add-suffix-to-symbol 'a "suffix"))

      (defgeneric with-quaternion-impl (q-sym body))

      (defmethod with-quaternion-impl ((q-sym symbol) body)
      (let
      ((q-realpart (add-suffix-to-symbol q-sym "realpart"))
      (q-i (add-suffix-to-symbol q-sym "i"))
      (q-j (add-suffix-to-symbol q-sym "j"))
      (q-k (add-suffix-to-symbol q-sym "k")))
      `(let
      ((,q-realpart (quat-realpart ,q-sym))
      (,q-i (quat-i ,q-sym))
      (,q-j (quat-j ,q-sym))
      (,q-k (quat-k ,q-sym)))
      (progn ,@body))))


      (defmacro with-quaternion (q-sym &rest body)
      (with-quaternion-impl q-sym body))


      (let
      ((my-quat '(1 2 3 4)))
      (with-quaternion my-quat
      (assert-equalp 1 |MY-QUAT-realpart|)
      (assert-equalp 2 |MY-QUAT-i|)
      (assert-equalp 3 |MY-QUAT-j|)
      (assert-equalp 4 |MY-QUAT-k|)))

      (let
      ((my-quat '(1 2 3 4)))
      (with-quaternion my-quat
      (assert-equalp 1 my-quat-realpart)
      (assert-equalp 2 my-quat-i)
      (assert-equalp 3 my-quat-j)
      (assert-equalp 4 my-quat-k)))


      When run under clisp, it prints the following symbol, clearly with escaped uppercase characters.



      |A-suffix|


      and produces the following error message:



      *** - PROGN: variable MY-QUAT-REALPART has no value






      common-lisp






      share|improve this question













      share|improve this question











      share|improve this question




      share|improve this question










      asked Nov 23 '18 at 23:41









      Gregory NisbetGregory Nisbet

      3,23121334




      3,23121334
























          2 Answers
          2






          active

          oldest

          votes


















          6














          Symbols in common lisp are interned in uppercase by default. The apparent case insensitivity is because everything you type is converted to uppercase at read/retrieval time, unless you use the special syntax with bar characters |My-case-sensitive-SYMBOL|. my-case-insensitive-symbol and MY-CASE-INSENSITIVE-SYMBOL refer to the same interned symbol, which is stored in all uppercase (though, this being common lisp, it is often possible to change that with command line options and reader macros). The symbol is actually not case insensitive at all, it just appears that way because most of the symbols in your code are uppercased by the reader, unless you specially exempt them from that by surrounding them in bar characters or purposely configuring an environment with unusual reader options.



          The net effect of all the above is that if you want to access a macro-generated symbol using the more familiar syntax, be sure to have all components uppercased before it's interned, e.g.:



          (add-suffix-to-symbol q-sym "I")


          instead of



          (add-suffix-to-symbol q-sym "i")


          Another option is to pass symbols to be concatenated rather than strings, e.g.



          (defun add-suffix-to-symbol (sym suffix)
          (intern (concatenate 'string "" (string sym) "-" (string suffix))))

          (print (add-suffix-to-symbol 'FOO 'bar)) ; foo-bar
          (print (add-suffix-to-symbol 'foo '|bar|)) ; |FOO-bar| because foo is converted to FOO at read time





          share|improve this answer

































            3














            To add a bit to Joe's answer:



            Symbols are a datatype with names, values, a property list and they may be interned in a package (another Lisp data structure).



            Symbols preserve their namestring cases



            You can create a symbol with its name from a string and also ask for the name of the symbol. A function to make a symbol is, well, make-symbol:



            CL-USER 8 > (make-symbol "This is A Symbol!!!***")
            #:|This is A Symbol!!!***|

            CL-USER 9 > (symbol-name (make-symbol "This is A Symbol!!!***"))
            "This is A Symbol!!!***"


            As you see the string is used as is and we get it out as it was provided. There is no case conversion.



            Escaping a symbol for the reader



            To print a symbol with different cases, whitespace and or special characters the symbol is escaped with surrounding | or single :



            CL-USER 11 > '|foo BAR ***# <>|
            |foo BAR ***# <>|

            CL-USER 12 > 'foo BAR ***# <>
            |foo BAR ***# <>|


            The reader is by default uppercasing unescaped input for symbol names



            The Lisp reader may use functions like find-symbol or intern to find or create symbols. Both can take a string as input and they are also case sensitive:



            CL-USER 15 > (let ((symbol '|foo|))
            (eq (find-symbol "FOO") symbol))
            NIL


            But the reader itself (used for example via read and read-from-string) is not case sensitive by default. By default all symbols get uppercased:



            CL-USER 21 > (symbol-name 'foo)
            "FOO"

            CL-USER 22 > (symbol-name 'FOO)
            "FOO"

            CL-USER 23 > (eq 'foo 'FOO)
            T


            We can check that both the printer and the reader are using uppercase by default:



            CL-USER 35 > *print-case*
            :UPCASE

            CL-USER 36 > (readtable-case *readtable*)
            :UPCASE


            When creating symbols in macros we usually want uppercase strings



            This means that when one creates symbols with names from strings, then one usually wants uppercase strings as input:



            lowercase:



            CL-USER 25 > (intern "zippy")
            |zippy|
            NIL


            uppercase:



            CL-USER 26 > (intern "ZIPPY")
            ZIPPY
            NIL


            In data we sometimes want mixed case symbols: escape them



            Sometimes we want to work with different cases: for example when the case needs to preserved because it is used as data:



            CL-USER 27 > (defvar *parents* '(|Eva Luator| |Ben BitDiddle jr.|))
            *PARENTS*

            CL-USER 28 > *parents*
            (|Eva Luator| |Ben BitDiddle jr.|)


            Creating uppercased symbol names with format



            Often in code one creates symbol names with format - which might be more concise than concatenate. One can then use format control strings, where the text or parts of it are uppercased by using ~:@( and ~):



            CL-USER 33 > (format nil "~:@(~a-~a-~a~)" "my" "macro" "name")
            "MY-MACRO-NAME"

            CL-USER 34 > (intern (format nil "~:@(~a-~a-~a~)" "my" "macro" "name"))
            MY-MACRO-NAME





            share|improve this answer


























              Your Answer






              StackExchange.ifUsing("editor", function () {
              StackExchange.using("externalEditor", function () {
              StackExchange.using("snippets", function () {
              StackExchange.snippets.init();
              });
              });
              }, "code-snippets");

              StackExchange.ready(function() {
              var channelOptions = {
              tags: "".split(" "),
              id: "1"
              };
              initTagRenderer("".split(" "), "".split(" "), channelOptions);

              StackExchange.using("externalEditor", function() {
              // Have to fire editor after snippets, if snippets enabled
              if (StackExchange.settings.snippets.snippetsEnabled) {
              StackExchange.using("snippets", function() {
              createEditor();
              });
              }
              else {
              createEditor();
              }
              });

              function createEditor() {
              StackExchange.prepareEditor({
              heartbeatType: 'answer',
              autoActivateHeartbeat: false,
              convertImagesToLinks: true,
              noModals: true,
              showLowRepImageUploadWarning: true,
              reputationToPostImages: 10,
              bindNavPrevention: true,
              postfix: "",
              imageUploader: {
              brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
              contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
              allowUrls: true
              },
              onDemand: true,
              discardSelector: ".discard-answer"
              ,immediatelyShowMarkdownHelp:true
              });


              }
              });














              draft saved

              draft discarded


















              StackExchange.ready(
              function () {
              StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53453935%2fcommon-lisp-add-suffix-to-symbol-for-use-in-macros%23new-answer', 'question_page');
              }
              );

              Post as a guest















              Required, but never shown

























              2 Answers
              2






              active

              oldest

              votes








              2 Answers
              2






              active

              oldest

              votes









              active

              oldest

              votes






              active

              oldest

              votes









              6














              Symbols in common lisp are interned in uppercase by default. The apparent case insensitivity is because everything you type is converted to uppercase at read/retrieval time, unless you use the special syntax with bar characters |My-case-sensitive-SYMBOL|. my-case-insensitive-symbol and MY-CASE-INSENSITIVE-SYMBOL refer to the same interned symbol, which is stored in all uppercase (though, this being common lisp, it is often possible to change that with command line options and reader macros). The symbol is actually not case insensitive at all, it just appears that way because most of the symbols in your code are uppercased by the reader, unless you specially exempt them from that by surrounding them in bar characters or purposely configuring an environment with unusual reader options.



              The net effect of all the above is that if you want to access a macro-generated symbol using the more familiar syntax, be sure to have all components uppercased before it's interned, e.g.:



              (add-suffix-to-symbol q-sym "I")


              instead of



              (add-suffix-to-symbol q-sym "i")


              Another option is to pass symbols to be concatenated rather than strings, e.g.



              (defun add-suffix-to-symbol (sym suffix)
              (intern (concatenate 'string "" (string sym) "-" (string suffix))))

              (print (add-suffix-to-symbol 'FOO 'bar)) ; foo-bar
              (print (add-suffix-to-symbol 'foo '|bar|)) ; |FOO-bar| because foo is converted to FOO at read time





              share|improve this answer






























                6














                Symbols in common lisp are interned in uppercase by default. The apparent case insensitivity is because everything you type is converted to uppercase at read/retrieval time, unless you use the special syntax with bar characters |My-case-sensitive-SYMBOL|. my-case-insensitive-symbol and MY-CASE-INSENSITIVE-SYMBOL refer to the same interned symbol, which is stored in all uppercase (though, this being common lisp, it is often possible to change that with command line options and reader macros). The symbol is actually not case insensitive at all, it just appears that way because most of the symbols in your code are uppercased by the reader, unless you specially exempt them from that by surrounding them in bar characters or purposely configuring an environment with unusual reader options.



                The net effect of all the above is that if you want to access a macro-generated symbol using the more familiar syntax, be sure to have all components uppercased before it's interned, e.g.:



                (add-suffix-to-symbol q-sym "I")


                instead of



                (add-suffix-to-symbol q-sym "i")


                Another option is to pass symbols to be concatenated rather than strings, e.g.



                (defun add-suffix-to-symbol (sym suffix)
                (intern (concatenate 'string "" (string sym) "-" (string suffix))))

                (print (add-suffix-to-symbol 'FOO 'bar)) ; foo-bar
                (print (add-suffix-to-symbol 'foo '|bar|)) ; |FOO-bar| because foo is converted to FOO at read time





                share|improve this answer




























                  6












                  6








                  6







                  Symbols in common lisp are interned in uppercase by default. The apparent case insensitivity is because everything you type is converted to uppercase at read/retrieval time, unless you use the special syntax with bar characters |My-case-sensitive-SYMBOL|. my-case-insensitive-symbol and MY-CASE-INSENSITIVE-SYMBOL refer to the same interned symbol, which is stored in all uppercase (though, this being common lisp, it is often possible to change that with command line options and reader macros). The symbol is actually not case insensitive at all, it just appears that way because most of the symbols in your code are uppercased by the reader, unless you specially exempt them from that by surrounding them in bar characters or purposely configuring an environment with unusual reader options.



                  The net effect of all the above is that if you want to access a macro-generated symbol using the more familiar syntax, be sure to have all components uppercased before it's interned, e.g.:



                  (add-suffix-to-symbol q-sym "I")


                  instead of



                  (add-suffix-to-symbol q-sym "i")


                  Another option is to pass symbols to be concatenated rather than strings, e.g.



                  (defun add-suffix-to-symbol (sym suffix)
                  (intern (concatenate 'string "" (string sym) "-" (string suffix))))

                  (print (add-suffix-to-symbol 'FOO 'bar)) ; foo-bar
                  (print (add-suffix-to-symbol 'foo '|bar|)) ; |FOO-bar| because foo is converted to FOO at read time





                  share|improve this answer















                  Symbols in common lisp are interned in uppercase by default. The apparent case insensitivity is because everything you type is converted to uppercase at read/retrieval time, unless you use the special syntax with bar characters |My-case-sensitive-SYMBOL|. my-case-insensitive-symbol and MY-CASE-INSENSITIVE-SYMBOL refer to the same interned symbol, which is stored in all uppercase (though, this being common lisp, it is often possible to change that with command line options and reader macros). The symbol is actually not case insensitive at all, it just appears that way because most of the symbols in your code are uppercased by the reader, unless you specially exempt them from that by surrounding them in bar characters or purposely configuring an environment with unusual reader options.



                  The net effect of all the above is that if you want to access a macro-generated symbol using the more familiar syntax, be sure to have all components uppercased before it's interned, e.g.:



                  (add-suffix-to-symbol q-sym "I")


                  instead of



                  (add-suffix-to-symbol q-sym "i")


                  Another option is to pass symbols to be concatenated rather than strings, e.g.



                  (defun add-suffix-to-symbol (sym suffix)
                  (intern (concatenate 'string "" (string sym) "-" (string suffix))))

                  (print (add-suffix-to-symbol 'FOO 'bar)) ; foo-bar
                  (print (add-suffix-to-symbol 'foo '|bar|)) ; |FOO-bar| because foo is converted to FOO at read time






                  share|improve this answer














                  share|improve this answer



                  share|improve this answer








                  edited Nov 24 '18 at 0:10

























                  answered Nov 23 '18 at 23:58









                  Joe TaylorJoe Taylor

                  763




                  763

























                      3














                      To add a bit to Joe's answer:



                      Symbols are a datatype with names, values, a property list and they may be interned in a package (another Lisp data structure).



                      Symbols preserve their namestring cases



                      You can create a symbol with its name from a string and also ask for the name of the symbol. A function to make a symbol is, well, make-symbol:



                      CL-USER 8 > (make-symbol "This is A Symbol!!!***")
                      #:|This is A Symbol!!!***|

                      CL-USER 9 > (symbol-name (make-symbol "This is A Symbol!!!***"))
                      "This is A Symbol!!!***"


                      As you see the string is used as is and we get it out as it was provided. There is no case conversion.



                      Escaping a symbol for the reader



                      To print a symbol with different cases, whitespace and or special characters the symbol is escaped with surrounding | or single :



                      CL-USER 11 > '|foo BAR ***# <>|
                      |foo BAR ***# <>|

                      CL-USER 12 > 'foo BAR ***# <>
                      |foo BAR ***# <>|


                      The reader is by default uppercasing unescaped input for symbol names



                      The Lisp reader may use functions like find-symbol or intern to find or create symbols. Both can take a string as input and they are also case sensitive:



                      CL-USER 15 > (let ((symbol '|foo|))
                      (eq (find-symbol "FOO") symbol))
                      NIL


                      But the reader itself (used for example via read and read-from-string) is not case sensitive by default. By default all symbols get uppercased:



                      CL-USER 21 > (symbol-name 'foo)
                      "FOO"

                      CL-USER 22 > (symbol-name 'FOO)
                      "FOO"

                      CL-USER 23 > (eq 'foo 'FOO)
                      T


                      We can check that both the printer and the reader are using uppercase by default:



                      CL-USER 35 > *print-case*
                      :UPCASE

                      CL-USER 36 > (readtable-case *readtable*)
                      :UPCASE


                      When creating symbols in macros we usually want uppercase strings



                      This means that when one creates symbols with names from strings, then one usually wants uppercase strings as input:



                      lowercase:



                      CL-USER 25 > (intern "zippy")
                      |zippy|
                      NIL


                      uppercase:



                      CL-USER 26 > (intern "ZIPPY")
                      ZIPPY
                      NIL


                      In data we sometimes want mixed case symbols: escape them



                      Sometimes we want to work with different cases: for example when the case needs to preserved because it is used as data:



                      CL-USER 27 > (defvar *parents* '(|Eva Luator| |Ben BitDiddle jr.|))
                      *PARENTS*

                      CL-USER 28 > *parents*
                      (|Eva Luator| |Ben BitDiddle jr.|)


                      Creating uppercased symbol names with format



                      Often in code one creates symbol names with format - which might be more concise than concatenate. One can then use format control strings, where the text or parts of it are uppercased by using ~:@( and ~):



                      CL-USER 33 > (format nil "~:@(~a-~a-~a~)" "my" "macro" "name")
                      "MY-MACRO-NAME"

                      CL-USER 34 > (intern (format nil "~:@(~a-~a-~a~)" "my" "macro" "name"))
                      MY-MACRO-NAME





                      share|improve this answer






























                        3














                        To add a bit to Joe's answer:



                        Symbols are a datatype with names, values, a property list and they may be interned in a package (another Lisp data structure).



                        Symbols preserve their namestring cases



                        You can create a symbol with its name from a string and also ask for the name of the symbol. A function to make a symbol is, well, make-symbol:



                        CL-USER 8 > (make-symbol "This is A Symbol!!!***")
                        #:|This is A Symbol!!!***|

                        CL-USER 9 > (symbol-name (make-symbol "This is A Symbol!!!***"))
                        "This is A Symbol!!!***"


                        As you see the string is used as is and we get it out as it was provided. There is no case conversion.



                        Escaping a symbol for the reader



                        To print a symbol with different cases, whitespace and or special characters the symbol is escaped with surrounding | or single :



                        CL-USER 11 > '|foo BAR ***# <>|
                        |foo BAR ***# <>|

                        CL-USER 12 > 'foo BAR ***# <>
                        |foo BAR ***# <>|


                        The reader is by default uppercasing unescaped input for symbol names



                        The Lisp reader may use functions like find-symbol or intern to find or create symbols. Both can take a string as input and they are also case sensitive:



                        CL-USER 15 > (let ((symbol '|foo|))
                        (eq (find-symbol "FOO") symbol))
                        NIL


                        But the reader itself (used for example via read and read-from-string) is not case sensitive by default. By default all symbols get uppercased:



                        CL-USER 21 > (symbol-name 'foo)
                        "FOO"

                        CL-USER 22 > (symbol-name 'FOO)
                        "FOO"

                        CL-USER 23 > (eq 'foo 'FOO)
                        T


                        We can check that both the printer and the reader are using uppercase by default:



                        CL-USER 35 > *print-case*
                        :UPCASE

                        CL-USER 36 > (readtable-case *readtable*)
                        :UPCASE


                        When creating symbols in macros we usually want uppercase strings



                        This means that when one creates symbols with names from strings, then one usually wants uppercase strings as input:



                        lowercase:



                        CL-USER 25 > (intern "zippy")
                        |zippy|
                        NIL


                        uppercase:



                        CL-USER 26 > (intern "ZIPPY")
                        ZIPPY
                        NIL


                        In data we sometimes want mixed case symbols: escape them



                        Sometimes we want to work with different cases: for example when the case needs to preserved because it is used as data:



                        CL-USER 27 > (defvar *parents* '(|Eva Luator| |Ben BitDiddle jr.|))
                        *PARENTS*

                        CL-USER 28 > *parents*
                        (|Eva Luator| |Ben BitDiddle jr.|)


                        Creating uppercased symbol names with format



                        Often in code one creates symbol names with format - which might be more concise than concatenate. One can then use format control strings, where the text or parts of it are uppercased by using ~:@( and ~):



                        CL-USER 33 > (format nil "~:@(~a-~a-~a~)" "my" "macro" "name")
                        "MY-MACRO-NAME"

                        CL-USER 34 > (intern (format nil "~:@(~a-~a-~a~)" "my" "macro" "name"))
                        MY-MACRO-NAME





                        share|improve this answer




























                          3












                          3








                          3







                          To add a bit to Joe's answer:



                          Symbols are a datatype with names, values, a property list and they may be interned in a package (another Lisp data structure).



                          Symbols preserve their namestring cases



                          You can create a symbol with its name from a string and also ask for the name of the symbol. A function to make a symbol is, well, make-symbol:



                          CL-USER 8 > (make-symbol "This is A Symbol!!!***")
                          #:|This is A Symbol!!!***|

                          CL-USER 9 > (symbol-name (make-symbol "This is A Symbol!!!***"))
                          "This is A Symbol!!!***"


                          As you see the string is used as is and we get it out as it was provided. There is no case conversion.



                          Escaping a symbol for the reader



                          To print a symbol with different cases, whitespace and or special characters the symbol is escaped with surrounding | or single :



                          CL-USER 11 > '|foo BAR ***# <>|
                          |foo BAR ***# <>|

                          CL-USER 12 > 'foo BAR ***# <>
                          |foo BAR ***# <>|


                          The reader is by default uppercasing unescaped input for symbol names



                          The Lisp reader may use functions like find-symbol or intern to find or create symbols. Both can take a string as input and they are also case sensitive:



                          CL-USER 15 > (let ((symbol '|foo|))
                          (eq (find-symbol "FOO") symbol))
                          NIL


                          But the reader itself (used for example via read and read-from-string) is not case sensitive by default. By default all symbols get uppercased:



                          CL-USER 21 > (symbol-name 'foo)
                          "FOO"

                          CL-USER 22 > (symbol-name 'FOO)
                          "FOO"

                          CL-USER 23 > (eq 'foo 'FOO)
                          T


                          We can check that both the printer and the reader are using uppercase by default:



                          CL-USER 35 > *print-case*
                          :UPCASE

                          CL-USER 36 > (readtable-case *readtable*)
                          :UPCASE


                          When creating symbols in macros we usually want uppercase strings



                          This means that when one creates symbols with names from strings, then one usually wants uppercase strings as input:



                          lowercase:



                          CL-USER 25 > (intern "zippy")
                          |zippy|
                          NIL


                          uppercase:



                          CL-USER 26 > (intern "ZIPPY")
                          ZIPPY
                          NIL


                          In data we sometimes want mixed case symbols: escape them



                          Sometimes we want to work with different cases: for example when the case needs to preserved because it is used as data:



                          CL-USER 27 > (defvar *parents* '(|Eva Luator| |Ben BitDiddle jr.|))
                          *PARENTS*

                          CL-USER 28 > *parents*
                          (|Eva Luator| |Ben BitDiddle jr.|)


                          Creating uppercased symbol names with format



                          Often in code one creates symbol names with format - which might be more concise than concatenate. One can then use format control strings, where the text or parts of it are uppercased by using ~:@( and ~):



                          CL-USER 33 > (format nil "~:@(~a-~a-~a~)" "my" "macro" "name")
                          "MY-MACRO-NAME"

                          CL-USER 34 > (intern (format nil "~:@(~a-~a-~a~)" "my" "macro" "name"))
                          MY-MACRO-NAME





                          share|improve this answer















                          To add a bit to Joe's answer:



                          Symbols are a datatype with names, values, a property list and they may be interned in a package (another Lisp data structure).



                          Symbols preserve their namestring cases



                          You can create a symbol with its name from a string and also ask for the name of the symbol. A function to make a symbol is, well, make-symbol:



                          CL-USER 8 > (make-symbol "This is A Symbol!!!***")
                          #:|This is A Symbol!!!***|

                          CL-USER 9 > (symbol-name (make-symbol "This is A Symbol!!!***"))
                          "This is A Symbol!!!***"


                          As you see the string is used as is and we get it out as it was provided. There is no case conversion.



                          Escaping a symbol for the reader



                          To print a symbol with different cases, whitespace and or special characters the symbol is escaped with surrounding | or single :



                          CL-USER 11 > '|foo BAR ***# <>|
                          |foo BAR ***# <>|

                          CL-USER 12 > 'foo BAR ***# <>
                          |foo BAR ***# <>|


                          The reader is by default uppercasing unescaped input for symbol names



                          The Lisp reader may use functions like find-symbol or intern to find or create symbols. Both can take a string as input and they are also case sensitive:



                          CL-USER 15 > (let ((symbol '|foo|))
                          (eq (find-symbol "FOO") symbol))
                          NIL


                          But the reader itself (used for example via read and read-from-string) is not case sensitive by default. By default all symbols get uppercased:



                          CL-USER 21 > (symbol-name 'foo)
                          "FOO"

                          CL-USER 22 > (symbol-name 'FOO)
                          "FOO"

                          CL-USER 23 > (eq 'foo 'FOO)
                          T


                          We can check that both the printer and the reader are using uppercase by default:



                          CL-USER 35 > *print-case*
                          :UPCASE

                          CL-USER 36 > (readtable-case *readtable*)
                          :UPCASE


                          When creating symbols in macros we usually want uppercase strings



                          This means that when one creates symbols with names from strings, then one usually wants uppercase strings as input:



                          lowercase:



                          CL-USER 25 > (intern "zippy")
                          |zippy|
                          NIL


                          uppercase:



                          CL-USER 26 > (intern "ZIPPY")
                          ZIPPY
                          NIL


                          In data we sometimes want mixed case symbols: escape them



                          Sometimes we want to work with different cases: for example when the case needs to preserved because it is used as data:



                          CL-USER 27 > (defvar *parents* '(|Eva Luator| |Ben BitDiddle jr.|))
                          *PARENTS*

                          CL-USER 28 > *parents*
                          (|Eva Luator| |Ben BitDiddle jr.|)


                          Creating uppercased symbol names with format



                          Often in code one creates symbol names with format - which might be more concise than concatenate. One can then use format control strings, where the text or parts of it are uppercased by using ~:@( and ~):



                          CL-USER 33 > (format nil "~:@(~a-~a-~a~)" "my" "macro" "name")
                          "MY-MACRO-NAME"

                          CL-USER 34 > (intern (format nil "~:@(~a-~a-~a~)" "my" "macro" "name"))
                          MY-MACRO-NAME






                          share|improve this answer














                          share|improve this answer



                          share|improve this answer








                          edited Nov 24 '18 at 9:41

























                          answered Nov 24 '18 at 9:34









                          Rainer JoswigRainer Joswig

                          112k8169290




                          112k8169290






























                              draft saved

                              draft discarded




















































                              Thanks for contributing an answer to Stack Overflow!


                              • Please be sure to answer the question. Provide details and share your research!

                              But avoid



                              • Asking for help, clarification, or responding to other answers.

                              • Making statements based on opinion; back them up with references or personal experience.


                              To learn more, see our tips on writing great answers.




                              draft saved


                              draft discarded














                              StackExchange.ready(
                              function () {
                              StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53453935%2fcommon-lisp-add-suffix-to-symbol-for-use-in-macros%23new-answer', 'question_page');
                              }
                              );

                              Post as a guest















                              Required, but never shown





















































                              Required, but never shown














                              Required, but never shown












                              Required, but never shown







                              Required, but never shown

































                              Required, but never shown














                              Required, but never shown












                              Required, but never shown







                              Required, but never shown







                              這個網誌中的熱門文章

                              Tangent Lines Diagram Along Smooth Curve

                              Yusuf al-Mu'taman ibn Hud

                              Zucchini