lispcommon-lispreader-macro

Use of # a.k.a. read-macro


Reading book "Let Over Lambda" by Doug Hoyte, I found the following description of #. sign, a.k.a. read-macro:

A basic read macro that comes built in with COMMON LISP is the #. read-time eval macro. This read macro lets you embed objects into the forms you read that can't be serialised, but can be created with a bit of lisp code.

It's from Chapter 4, most part of the book can be found here: http://letoverlambda.com/index.cl/toc

This is example from the book that shows how the same expression may be read differently every time:

* '(football-game
     (game-started-at
       #.(get-internal-real-time))
     (coin-flip
       #.(if (zerop (random 2)) 'heads 'tails)))

(FOOTBALL-GAME
  (GAME-STARTED-AT 187)
  (COIN-FLIP HEADS))

* '(football-game
     (game-started-at
       #.(get-internal-real-time))
     (coin-flip
   #.(if (zerop (random 2)) 'heads 'tails)))

(FOOTBALL-GAME
  (GAME-STARTED-AT 309)
  (COIN-FLIP TAILS))

Next, author demonstrates some hardcore tricks, creating variations with # macro.

So, it turns out that #' is also some kind of reading macro, and it's usually used before symbols that represent names of functions. But is it necessary, and what's exactly his job there?

I can put symbol for higher-order functions with #' or without it:

CL-USER> (defun test nil t)
TEST
CL-USER> (funcall #'test)
T
CL-USER> (funcall 'test)
T

with the same success.


Solution

  • You can call global definitions of functions both ways:

    CL-USER> (defun test nil t)
    TEST
    CL-USER> (funcall #'test)
    T
    CL-USER> (funcall 'test)
    T
    

    But see this:

    CL-USER 10 > (defun foo () 42)
    FOO
    
    CL-USER 11 > (flet ((foo () 82))
                   (print (foo))
                   (print (funcall 'foo))
                   (print (funcall #'foo)))
    
    82   ; the local definition
    42   ; the symbol references the global definition
    82   ; (function foo) / #'foo  references the local definition
    

    (funcall 'foo) looks up the function from the symbol.

    (funcall #'foo) calls the function from the lexical environment. If there is none the global definition is used.

    #'foo is a shorthand notation for (function foo).

    CL-USER 19 > '#'foo
    (FUNCTION FOO)