Search code examples
lispcommon-lisp

What is the difference between #\ , ' and #'?


In Common Lisp, given that "a" is simply a character, what is the difference between #\a, 'a #'a?

My question comes from the tutorialspoint.com tutorial on Lisp. At one point the tutorial introduces:

; a character array with all initial elements set to a
; is a string actually
(write(make-array 10 :element-type 'character :initial-element #\a)) 
(terpri)

; a two dimensional array with initial values a
(setq myarray (make-array '(2 2) :initial-element 'a :adjustable t))
(write myarray)
(terpri)

With the output:

"aaaaaaaaaa"
#2A((A A) (A A))

#' is not included in this example but I'm including it in the question because it can be confusing as well. 🙂

Thank you very much! 😊


Solution

  • To start, a is not "simply a character." The Lisp reader parses #\a as the character literal a, which is an object in Common Lisp. Note that #\a and #\A are different character objects.

    When the Lisp reader encounters a single quote, the expression following the single quote is not evaluated. Specifically, 'a is treated as (quote a), where quote returns its argument unevaluated. Now, a is a symbol, so 'a evaluates to that symbol. But the Lisp reader upcases most characters it reads by default, so 'a really evaluates to the symbol A. The good news is that whether you type a or A, the Lisp reader will read A (unless you mess with the readtable), and both 'a and 'A evaluate to the symbol A.

    When the Lisp reader encounters #'a, the entire expression is treated as (function a), which when evaluated returns the function associated with the name a. But, note that it is an error to use function, and by extension #', on an identifier that does not denote a function.

    To clarify this last part a bit, consider the following REPL interaction:

    CL-USER> (defvar a 1)
    A
    CL-USER> a
    1
    CL-USER> #'a
    
    The function COMMON-LISP-USER::A is undefined.
       [Condition of type UNDEFINED-FUNCTION]
    

    Here the variable a is defined and given the value 1, but when we try to access the function denoted by a we get an error message because there is no such function. Continuing:

    ; Evaluation aborted on #<UNDEFINED-FUNCTION A {1002DDC303}>.
    CL-USER> (defun a (x) x)
    A
    CL-USER> (a 'b)
    B
    CL-USER> a
    1
    CL-USER> #'a
    #<FUNCTION A>
    

    Now we have defined a function named a that simply returns its argument. You can see that when we call a with an argument 'b we get the expected result: (a 'b) --> b. But, then when we evaluate a alone we still get 1. Symbols in Common Lisp are objects that have, among other cells, value cells and function cells. After the above interaction, the symbol a now has 1 in its value cell, and it has the function we have defined in its function cell. When the symbol a is evaluated the value cell is accessed, but when (function a) or #'a is evaluated, the function cell is accessed. You can see above that when #'a is evaluated, the function we defined is returned, and the REPL prints #<FUNCTION A> to show this.

    As an aside, I wouldn't recommend using Tutorialspoint to learn Common Lisp. Glancing over the site, right away I see this:

    LISP expressions are case-insensitive, cos 45 or COS 45 are same.

    This is just wrong. And, Lisp is not written in all-caps. None of this inspires faith. Instead, find a good book. There are some recommendations on the tag-info page.