Search code examples
common-lispsymbols

Backquote symbol list ending in period


I'm curious if there is a way to end a backquoted symbol list with a period following a comma inserted value.

Here is the sample code:

(defparameter *things* '(book pencil shoe))
(defun inspect-item (item things)
    (if (member item things)
        `(you pick up the ,item and yeet it out the window.)
        `(only realize the truth... there is no ,item.)))

This will succeed (print (inspect-item 'book *things*)) and it produces the symbol list (YOU PICK UP THE BOOK AND YEET IT OUT THE WINDOW.). I assume in this case that the period is part of the symbol WINDOW. (as confirmed using the last function).

However, this will fail (print (inspect-item 'spoon *things*)) claiming that variable ITEM. has no value (Because it thinks the name is item.). Leaving a space between item and the period gives the error illegal end of dotted list which I assume is because it is assuming I'm using dotted list syntax.

Is there any way to get it to produce the symbol I want at the end (BOOK.)?


Solution

  • Possible requirements for a solution

    You need to create a new symbol based on an old one:

    • the same name, with a . appended
    • probably in the same package

    Period as a symbol

    Note that you can write a symbol with the period as a name using an escaped symbol: |.| or \..

    CL-USER 17 > (let ((item 'foobar))
                   `(only realize the truth... there is no ,item \.))
    (ONLY REALIZE THE TRUTH... THERE IS NO FOOBAR \.)
    

    princ prints without escape characters:

    CL-USER 18 > (princ '(ONLY REALIZE THE TRUTH... THERE IS NO FOOBAR \.))
    (ONLY REALIZE THE TRUTH... THERE IS NO FOOBAR .)       ; <- printed output
    (ONLY REALIZE THE TRUTH... THERE IS NO FOOBAR \.)      ; <- REPL value
    

    Solution

    CL-USER 19 > (defun add-suffix (symbol suffix)
                   (intern (concatenate 'string
                                        (symbol-name symbol)
                                        (symbol-name suffix))
                           (symbol-package symbol)))
    ADD-SUFFIX
    
    CL-USER 20 > (let ((item 'tree))
                   `(we went to the ,(add-suffix item '|.|)))
    (WE WENT TO THE TREE.)
    

    It can also be useful to use the flexibility of format instead of using concatenate.

    CL-USER 22 > (defun add-suffix (symbol suffix)
                   (intern (format nil "~a~a" symbol suffix)
                           (symbol-package symbol)))
    ADD-SUFFIX