Here is a couple of hopefully portable ANSI Common Lisp functions that will help you explore available objects (symbols). In this post you’ll find:

    • OBLIST, a function that returns a list of all objects
    • ??, ?f, ?v, ?t, and ?s, functions that will fetch the whole description or documentation strings of a symbol
    • SYMBOL->CELLS, a function that returns the cells of a symbol (name, value, function, plist, package, docstrings) as an alist
    • OBLIST-WITH-CELLS, like OBLIST, but returns a list of cells for each symbol
    • introspection.lisp, the source file with all those functions.
CL-USER> (oblist-with-cells (list '?v '?f '*FEATURES*))
(((NAME . "?V") (PACKAGE . "COMMON-LISP-USER") (VALUE . UNBOUND)
  (PLIST . UNBOUND) (FUNCTION . #)
  (FUNCTION-DOC . "Documentation string of a variable"))
 ((NAME . "?F") (PACKAGE . "COMMON-LISP-USER") (VALUE . UNBOUND)
  (PLIST . UNBOUND) (FUNCTION . #)
  (FUNCTION-DOC . "Documentation string of a function"))
 ((NAME . "*FEATURES*") (PACKAGE . "COMMON-LISP")
  (VALUE :SWANK :SB-BSD-SOCKETS-ADDRINFO :ASDF2 :ASDF :ANSI-CL :COMMON-LISP
   :SBCL :SB-DOC :SB-TEST :SB-LDB :SB-PACKAGE-LOCKS :SB-UNICODE :SB-EVAL
   :SB-SOURCE-LOCATIONS :IEEE-FLOATING-POINT :X86-64 :UNIX :BSD :ELF :FREEBSD
   :GCC-TLS :GENCGC :STACK-GROWS-DOWNWARD-NOT-UPWARD :C-STACK-IS-CONTROL-STACK
   :LINKAGE-TABLE :COMPARE-AND-SWAP-VOPS :UNWIND-TO-FRAME-AND-CALL-VOP
   :RAW-INSTANCE-INIT-VOPS :STACK-ALLOCATABLE-CLOSURES
   :STACK-ALLOCATABLE-VECTORS :STACK-ALLOCATABLE-LISTS
   :STACK-ALLOCATABLE-FIXED-OBJECTS :ALIEN-CALLBACKS :CYCLE-COUNTER
   :COMPLEX-FLOAT-VOPS :FLOAT-EQL-VOPS :INLINE-CONSTANTS :MEMORY-BARRIER-VOPS
   :MULTIPLY-HIGH-VOPS :OS-PROVIDES-DLOPEN :OS-PROVIDES-DLADDR
   :OS-PROVIDES-PUTWC :OS-PROVIDES-BLKSIZE-T :OS-PROVIDES-SUSECONDS-T
   :OS-PROVIDES-GETPROTOBY-R :OS-PROVIDES-POLL)
  (PLIST . UNBOUND) (FUNCTION . UNBOUND)
  (VALUE-DOC . "a list of symbols that describe features provided by the
   implementation")))
CL-USER>

Or, if you prefer, you can get a very long list by omitting the list of objects that you want to look at:

CL-USER (oblist-with-cells)
(... a very long list omitted ...)
CL-USER>

If the list doesn’t look pretty, you can format it with the pretty printer PPRINT. Here’s an example using ccl:

CL-USER> (oblist-with-cells (list '?v '?f))
(((NAME . "?V") (PACKAGE . "COMMON-LISP-USER") (VALUE . UNBOUND) (PLIST . UNBOU\
ND) (FUNCTION . #<Compiled-function ?V #x30200080D8DF>) (FUNCTION-DOC . "Docume\
ntation string of a variable")) ((NAME . "?F") (PACKAGE . "COMMON-LISP-USER") (\
VALUE . UNBOUND) (PLIST . UNBOUND) (FUNCTION . #<Compiled-function ?F #x3020008\
0DC3F>) (FUNCTION-DOC . "Documentation string of a function")))
 
CL-USER> (pprint (oblist-with-cells (list '?v '?f)))
 
(((NAME . "?V") (PACKAGE . "COMMON-LISP-USER") (VALUE . UNBOUND)
  (PLIST . UNBOUND) (FUNCTION . #<Compiled-function ?V #x30200080D8DF>)
  (FUNCTION-DOC . "Documentation string of a variable"))
 ((NAME . "?F") (PACKAGE . "COMMON-LISP-USER") (VALUE . UNBOUND)
  (PLIST . UNBOUND) (FUNCTION . #<Compiled-function ?F #x30200080DC3F>)
  (FUNCTION-DOC . "Documentation string of a function"))); No value
CL-USER>

Further reading

You may want to read about the ANSI Common Lisp function INSPECT, and check out the introspections of the SLIME ide for further ideas. Of course, you can also look at the source code of major ANSI Common Lisp implementations’ introspection functions like DESCRIBE and friends to see how they get at the internals of a symbol.

The file introspection.lisp

All functions above are defined in the file introspection.lisp below. You can use these functions by calling (LOAD "introspection.lisp") in your own programs or at the read-eval-print loop (REPL).

;;;; introspection.lisp -- functions to inspect ANSI Common Lisp environment
 
;;;; License: 2-clauses BSD
;;
;; Copyright (c) 2012 Farid Hajji. All rights reserved.
;;
;; Redistribution and use in source and binary forms, with or without
;; modification, are permitted provided that the following conditions
;; are met:
;; 1. Redistributions of source code must retain the above copyright
;; notice, this list of conditions and the following disclaimer.
;; 2. Redistributions in binary form must reproduce the above copyright
;; notice, this list of conditions and the following disclaimer in the
;; documentation and/or other materials provided with the distribution.
;;
;; THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
;; ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
;; IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
;; ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
;; FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
;; DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
;; OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
;; HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
;; LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
;; OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
;; SUCH DAMAGE.
;;;;
 
;;; OBLIST returns a list of all available symbols
 
(defun oblist (&amp;optional (packagename "COMMON-LISP-USER"))
"Return a list of all symbols in PACKAGENAME"
(let ((the-symbols ()))
;; DO-SYMBOLS is a common-lisp function
(do-symbols (var packagename)
(setf the-symbols (cons var the-symbols)))
(setf the-symbols (sort the-symbols #'string-lessp))
the-symbols))
 
;;; The ?X functions retrieve some informations about specific symbols
 
(defun ?? (some-symbol)
"Verbosely describe a symbol using #'describe"
(describe some-symbol))
 
(defun ?f (some-function)
"Documentation string of a function"
(documentation some-function 'function))
 
(defun ?v (some-variable)
"Documentation string of a variable"
(documentation some-variable 'variable))
 
(defun ?t (some-type)
(documentation some-type 'type))
 
(defun ?s (some-structure)
(documentation some-structure 'structure))
 
;;; The SYMBOL-&gt;XXX functions return the content of specific symbol cells
;;; (See HyperSpec, CLHS: System Class Symbol for the following functions)
 
(defconstant U-VALUE 'unbound "Represents an unbound value")
(defconstant U-PLIST 'unbound "Represents an unbound p-list")
(defconstant U-FUNCTION 'unbound "Represents an unbound function")
 
(defun symbol-&gt;name (symbol)
"Return the NAME of SYMBOL as a STRING"
(symbol-name symbol))
 
(defun symbol-&gt;package (symbol)
"Return the PACKAGE of SYMBOL as a STRING"
(package-name (symbol-package symbol)))
 
(defun symbol-&gt;plist (symbol)
"Return the PLIST of SYMBOL as a PLIST, or U-PLIST if unbound"
(let ((plist (symbol-plist symbol)))
(if plist
plist
U-PLIST)))
 
(defun symbol-&gt;value (symbol)
"Return the VALUE of SYMBOL. If unbound, return U-VALUE"
(if (boundp symbol)
(symbol-value symbol)
U-VALUE))
 
(defun symbol-&gt;function (symbol)
"Return the representation of a function of SYMBOL, or U-FUNCTION"
(if (fboundp symbol)
(symbol-function symbol)
U-FUNCTION))
 
(defun symbol-&gt;cells (symbol)
"Create an alist representing SYMBOL's cells"
(let ((alist ()))
;; optional documentation strings
(when (fboundp symbol) (push (cons 'function-doc (?f symbol)) alist))
(when (boundp symbol) (push (cons 'value-doc (?v symbol)) alist))
 
;; the following are cells of a symbol
(push (cons 'function (symbol-&gt;function symbol)) alist)
(push (cons 'plist (symbol-&gt;plist symbol)) alist)
(push (cons 'value (symbol-&gt;value symbol)) alist)
(push (cons 'package (symbol-&gt;package symbol)) alist)
(push (cons 'name (symbol-&gt;name symbol)) alist)
 
;; return value
alist))
 
;;; OBLIST-WITH-CELLS is an OBLIST that returns a list of alists (cells)
 
(defun oblist-with-cells (&amp;optional (symbol-list (oblist)))
"Apply SYMBOL-&gt;CELLS on all SYMBOLs in SYMBOL-LIST"
(mapcar #'symbol-&gt;cells symbol-list))
 
;;; That's all, folks!

OBLIST

The problem: you’ve just started your favorite ANSI Common Lisp implementation and you’re at the REPL top level. Now you may be wondering what functions and variables, or more generally what symbols, are available to you. You may want to explore your Lisp, and you either don’t use an IDE, or your IDE doesn’t feature a symbol browser.

So, what do you need? Some old Lisp implementations provided a function OBLIST (short for OBject LIST) that returned a list of all objects, but there’s no OBLIST in ANSI Common Lisp.

Fortunately, all is not lost: we can roll our own OBLIST portably, using nothing more than pure ANSI Common Lisp:

;;; OBLIST returns a list of all available symbols
 
(defun oblist (&amp;optional (packagename "COMMON-LISP-USER"))
    "Return a list of all symbols in PACKAGENAME"
    (let ((the-symbols ()))
        ;; DO-SYMBOLS is a common-lisp function
        (do-symbols (var packagename)
            (setf the-symbols (cons var the-symbols)))
            (setf the-symbols (sort the-symbols #'string-lessp))
        the-symbols))

OBLIST relies on the ANSI Common Lisp function DO-SYMBOLS to do its job.

At the REPL of your favorite Lisp, just call (oblist) to get a list of all symbols in the default “COMMON-LISP-USER” package. Alternatively, you can also ask for all symbols of a specific package by providing its name (as a string) to OBLIST, e.g. by calling (oblist "COMMON-LISP"). Remember to LOAD the file containing the definition of OBLIST beforehand:

CL-USER> (load "introspection.lisp")
T
CL-USER> (oblist "COMMON-LISP")
(&ALLOW-OTHER-KEYS &AUX &BODY &ENVIRONMENT &KEY &OPTIONAL &REST &WHOLE * ** ***
 *BREAK-ON-SIGNALS* *COMPILE-FILE-PATHNAME* *COMPILE-FILE-TRUENAME*
 *COMPILE-PRINT* *COMPILE-VERBOSE* *DEBUG-IO* *DEBUGGER-HOOK*
 *DEFAULT-PATHNAME-DEFAULTS* *ERROR-OUTPUT* *FEATURES* *GENSYM-COUNTER*
 *LOAD-PATHNAME* *LOAD-PRINT* *LOAD-TRUENAME* *LOAD-VERBOSE* *MACROEXPAND-HOOK*
 *MODULES* *PACKAGE* *PRINT-ARRAY* *PRINT-BASE* *PRINT-CASE* *PRINT-CIRCLE*
 *PRINT-ESCAPE* *PRINT-GENSYM* *PRINT-LENGTH* *PRINT-LEVEL* *PRINT-LINES*
 *PRINT-MISER-WIDTH* *PRINT-PPRINT-DISPATCH* *PRINT-PRETTY* *PRINT-RADIX*
 *PRINT-READABLY* *PRINT-RIGHT-MARGIN* *QUERY-IO* *RANDOM-STATE* *READ-BASE*
 *READ-DEFAULT-FLOAT-FORMAT* *READ-EVAL* *READ-SUPPRESS* *READTABLE*
 *STANDARD-INPUT* *STANDARD-OUTPUT* *TERMINAL-IO* *TRACE-OUTPUT* + ++ +++ - /
 // /// /= 1+ 1- < <= = > >= ABORT ABS ACONS ACOS ACOSH ADD-METHOD ADJOIN
 ADJUST-ARRAY ADJUSTABLE-ARRAY-P ALLOCATE-INSTANCE ALPHA-CHAR-P ALPHANUMERICP
 AND APPEND APPLY APROPOS APROPOS-LIST AREF ARITHMETIC-ERROR
 ARITHMETIC-ERROR-OPERANDS ARITHMETIC-ERROR-OPERATION ARRAY ARRAY-DIMENSION
 ARRAY-DIMENSION-LIMIT ARRAY-DIMENSIONS ARRAY-DISPLACEMENT ARRAY-ELEMENT-TYPE
 ARRAY-HAS-FILL-POINTER-P ARRAY-IN-BOUNDS-P ARRAY-RANK ARRAY-RANK-LIMIT
 ARRAY-ROW-MAJOR-INDEX ARRAY-TOTAL-SIZE ARRAY-TOTAL-SIZE-LIMIT ARRAYP ASH ASIN
 ASINH ASSERT ASSOC ASSOC-IF ASSOC-IF-NOT ATAN ATANH ATOM BASE-CHAR BASE-STRING
 BIGNUM BIT BIT-AND BIT-ANDC1 BIT-ANDC2 BIT-EQV BIT-IOR BIT-NAND BIT-NOR
 BIT-NOT BIT-ORC1 BIT-ORC2 BIT-VECTOR BIT-VECTOR-P BIT-XOR BLOCK BOOLE BOOLE-1
 BOOLE-2 BOOLE-AND BOOLE-ANDC1 BOOLE-ANDC2 BOOLE-C1 BOOLE-C2 BOOLE-CLR
 BOOLE-EQV BOOLE-IOR BOOLE-NAND BOOLE-NOR BOOLE-ORC1 BOOLE-ORC2 BOOLE-SET
 BOOLE-XOR BOOLEAN BOTH-CASE-P BOUNDP BREAK BROADCAST-STREAM
 BROADCAST-STREAM-STREAMS BUILT-IN-CLASS BUTLAST BYTE BYTE-POSITION BYTE-SIZE
 CAAAAR CAAADR CAAAR CAADAR CAADDR CAADR CAAR CADAAR CADADR CADAR CADDAR CADDDR
 CADDR CADR CALL-ARGUMENTS-LIMIT CALL-METHOD CALL-NEXT-METHOD CAR CASE CATCH
 CCASE CDAAAR CDAADR CDAAR CDADAR CDADDR CDADR CDAR CDDAAR CDDADR CDDAR CDDDAR
 CDDDDR CDDDR CDDR CDR CEILING CELL-ERROR CELL-ERROR-NAME CERROR CHANGE-CLASS
 CHAR CHAR-CODE CHAR-CODE-LIMIT CHAR-DOWNCASE CHAR-EQUAL CHAR-GREATERP CHAR-INT
 CHAR-LESSP CHAR-NAME CHAR-NOT-EQUAL CHAR-NOT-GREATERP CHAR-NOT-LESSP
 CHAR-UPCASE CHAR/= CHAR< CHAR<= CHAR= CHAR> CHAR>= CHARACTER CHARACTERP
 CHECK-TYPE CIS CLASS CLASS-NAME CLASS-OF CLEAR-INPUT CLEAR-OUTPUT CLOSE
 CLRHASH CODE-CHAR COERCE COMPILATION-SPEED COMPILE COMPILE-FILE
 COMPILE-FILE-PATHNAME COMPILED-FUNCTION COMPILED-FUNCTION-P COMPILER-MACRO
 COMPILER-MACRO-FUNCTION COMPLEMENT COMPLEX COMPLEXP COMPUTE-APPLICABLE-METHODS
 COMPUTE-RESTARTS CONCATENATE CONCATENATED-STREAM CONCATENATED-STREAM-STREAMS
 COND CONDITION CONJUGATE CONS CONSP CONSTANTLY CONSTANTP CONTINUE
 CONTROL-ERROR COPY-ALIST COPY-LIST COPY-PPRINT-DISPATCH COPY-READTABLE
 COPY-SEQ COPY-STRUCTURE COPY-SYMBOL COPY-TREE COS COSH COUNT COUNT-IF
 COUNT-IF-NOT CTYPECASE DEBUG DECF DECLAIM DECLARATION DECLARE DECODE-FLOAT
 DECODE-UNIVERSAL-TIME DEFCLASS DEFCONSTANT DEFGENERIC DEFINE-COMPILER-MACRO
 DEFINE-CONDITION DEFINE-METHOD-COMBINATION DEFINE-MODIFY-MACRO
 DEFINE-SETF-EXPANDER DEFINE-SYMBOL-MACRO DEFMACRO DEFMETHOD DEFPACKAGE
 DEFPARAMETER DEFSETF DEFSTRUCT DEFTYPE DEFUN DEFVAR DELETE DELETE-DUPLICATES
 DELETE-FILE DELETE-IF DELETE-IF-NOT DELETE-PACKAGE DENOMINATOR DEPOSIT-FIELD
 DESCRIBE DESCRIBE-OBJECT DESTRUCTURING-BIND DIGIT-CHAR DIGIT-CHAR-P DIRECTORY
 DIRECTORY-NAMESTRING DISASSEMBLE DIVISION-BY-ZERO DO DO* DO-ALL-SYMBOLS
 DO-EXTERNAL-SYMBOLS DO-SYMBOLS DOCUMENTATION DOLIST DOTIMES DOUBLE-FLOAT
 DOUBLE-FLOAT-EPSILON DOUBLE-FLOAT-NEGATIVE-EPSILON DPB DRIBBLE DYNAMIC-EXTENT
 ECASE ECHO-STREAM ECHO-STREAM-INPUT-STREAM ECHO-STREAM-OUTPUT-STREAM ED EIGHTH
 ELT ENCODE-UNIVERSAL-TIME END-OF-FILE ENDP ENOUGH-NAMESTRING
 ENSURE-DIRECTORIES-EXIST ENSURE-GENERIC-FUNCTION EQ EQL EQUAL EQUALP ERROR
 ETYPECASE EVAL EVAL-WHEN EVENP EVERY EXP EXPORT EXPT EXTENDED-CHAR FBOUNDP
 FCEILING FDEFINITION FFLOOR FIFTH FILE-AUTHOR FILE-ERROR FILE-ERROR-PATHNAME
 FILE-LENGTH FILE-NAMESTRING FILE-POSITION FILE-STREAM FILE-STRING-LENGTH
 FILE-WRITE-DATE FILL FILL-POINTER FIND FIND-ALL-SYMBOLS FIND-CLASS FIND-IF
 FIND-IF-NOT FIND-METHOD FIND-PACKAGE FIND-RESTART FIND-SYMBOL FINISH-OUTPUT
 FIRST FIXNUM FLET FLOAT FLOAT-DIGITS FLOAT-PRECISION FLOAT-RADIX FLOAT-SIGN
 FLOATING-POINT-INEXACT FLOATING-POINT-INVALID-OPERATION
 FLOATING-POINT-OVERFLOW FLOATING-POINT-UNDERFLOW FLOATP FLOOR FMAKUNBOUND
 FORCE-OUTPUT FORMAT FORMATTER FOURTH FRESH-LINE FROUND FTRUNCATE FTYPE FUNCALL
 FUNCTION FUNCTION-KEYWORDS FUNCTION-LAMBDA-EXPRESSION FUNCTIONP GCD
 GENERIC-FUNCTION GENSYM GENTEMP GET GET-DECODED-TIME
 GET-DISPATCH-MACRO-CHARACTER GET-INTERNAL-REAL-TIME GET-INTERNAL-RUN-TIME
 GET-MACRO-CHARACTER GET-OUTPUT-STREAM-STRING GET-PROPERTIES GET-SETF-EXPANSION
 GET-UNIVERSAL-TIME GETF GETHASH GO GRAPHIC-CHAR-P HANDLER-BIND HANDLER-CASE
 HASH-TABLE HASH-TABLE-COUNT HASH-TABLE-P HASH-TABLE-REHASH-SIZE
 HASH-TABLE-REHASH-THRESHOLD HASH-TABLE-SIZE HASH-TABLE-TEST HOST-NAMESTRING
 IDENTITY IF IGNORABLE IGNORE IGNORE-ERRORS IMAGPART IMPORT IN-PACKAGE INCF
 INITIALIZE-INSTANCE INLINE INPUT-STREAM-P INSPECT INTEGER INTEGER-DECODE-FLOAT
 INTEGER-LENGTH INTEGERP INTERACTIVE-STREAM-P INTERN
 INTERNAL-TIME-UNITS-PER-SECOND INTERSECTION INVALID-METHOD-ERROR
 INVOKE-DEBUGGER INVOKE-RESTART INVOKE-RESTART-INTERACTIVELY ISQRT KEYWORD
 KEYWORDP LABELS LAMBDA LAMBDA-LIST-KEYWORDS LAMBDA-PARAMETERS-LIMIT LAST LCM
 LDB LDB-TEST LDIFF LEAST-NEGATIVE-DOUBLE-FLOAT LEAST-NEGATIVE-LONG-FLOAT
 LEAST-NEGATIVE-NORMALIZED-DOUBLE-FLOAT LEAST-NEGATIVE-NORMALIZED-LONG-FLOAT
 LEAST-NEGATIVE-NORMALIZED-SHORT-FLOAT LEAST-NEGATIVE-NORMALIZED-SINGLE-FLOAT
 LEAST-NEGATIVE-SHORT-FLOAT LEAST-NEGATIVE-SINGLE-FLOAT
 LEAST-POSITIVE-DOUBLE-FLOAT LEAST-POSITIVE-LONG-FLOAT
 LEAST-POSITIVE-NORMALIZED-DOUBLE-FLOAT LEAST-POSITIVE-NORMALIZED-LONG-FLOAT
 LEAST-POSITIVE-NORMALIZED-SHORT-FLOAT LEAST-POSITIVE-NORMALIZED-SINGLE-FLOAT
 LEAST-POSITIVE-SHORT-FLOAT LEAST-POSITIVE-SINGLE-FLOAT LENGTH LET LET*
 LISP-IMPLEMENTATION-TYPE LISP-IMPLEMENTATION-VERSION LIST LIST*
 LIST-ALL-PACKAGES LIST-LENGTH LISTEN LISTP LOAD
 LOAD-LOGICAL-PATHNAME-TRANSLATIONS LOAD-TIME-VALUE LOCALLY LOG LOGAND LOGANDC1
 LOGANDC2 LOGBITP LOGCOUNT LOGEQV LOGICAL-PATHNAME
 LOGICAL-PATHNAME-TRANSLATIONS LOGIOR LOGNAND LOGNOR LOGNOT LOGORC1 LOGORC2
 LOGTEST LOGXOR LONG-FLOAT LONG-FLOAT-EPSILON LONG-FLOAT-NEGATIVE-EPSILON
 LONG-SITE-NAME LOOP LOOP-FINISH LOWER-CASE-P MACHINE-INSTANCE MACHINE-TYPE
 MACHINE-VERSION MACRO-FUNCTION MACROEXPAND MACROEXPAND-1 MACROLET MAKE-ARRAY
 MAKE-BROADCAST-STREAM MAKE-CONCATENATED-STREAM MAKE-CONDITION
 MAKE-DISPATCH-MACRO-CHARACTER MAKE-ECHO-STREAM MAKE-HASH-TABLE MAKE-INSTANCE
 MAKE-INSTANCES-OBSOLETE MAKE-LIST MAKE-LOAD-FORM MAKE-LOAD-FORM-SAVING-SLOTS
 MAKE-METHOD MAKE-PACKAGE MAKE-PATHNAME MAKE-RANDOM-STATE MAKE-SEQUENCE
 MAKE-STRING MAKE-STRING-INPUT-STREAM MAKE-STRING-OUTPUT-STREAM MAKE-SYMBOL
 MAKE-SYNONYM-STREAM MAKE-TWO-WAY-STREAM MAKUNBOUND MAP MAP-INTO MAPC MAPCAN
 MAPCAR MAPCON MAPHASH MAPL MAPLIST MASK-FIELD MAX MEMBER MEMBER-IF
 MEMBER-IF-NOT MERGE MERGE-PATHNAMES METHOD METHOD-COMBINATION
 METHOD-COMBINATION-ERROR METHOD-QUALIFIERS MIN MINUSP MISMATCH MOD
 MOST-NEGATIVE-DOUBLE-FLOAT MOST-NEGATIVE-FIXNUM MOST-NEGATIVE-LONG-FLOAT
 MOST-NEGATIVE-SHORT-FLOAT MOST-NEGATIVE-SINGLE-FLOAT
 MOST-POSITIVE-DOUBLE-FLOAT MOST-POSITIVE-FIXNUM MOST-POSITIVE-LONG-FLOAT
 MOST-POSITIVE-SHORT-FLOAT MOST-POSITIVE-SINGLE-FLOAT MUFFLE-WARNING
 MULTIPLE-VALUE-BIND MULTIPLE-VALUE-CALL MULTIPLE-VALUE-LIST
 MULTIPLE-VALUE-PROG1 MULTIPLE-VALUE-SETQ MULTIPLE-VALUES-LIMIT NAME-CHAR
 NAMESTRING NBUTLAST NCONC NEXT-METHOD-P NIL NINTERSECTION NINTH
 NO-APPLICABLE-METHOD NO-NEXT-METHOD NOT NOTANY NOTEVERY NOTINLINE NRECONC
 NREVERSE NSET-DIFFERENCE NSET-EXCLUSIVE-OR NSTRING-CAPITALIZE NSTRING-DOWNCASE
 NSTRING-UPCASE NSUBLIS NSUBST NSUBST-IF NSUBST-IF-NOT NSUBSTITUTE
 NSUBSTITUTE-IF NSUBSTITUTE-IF-NOT NTH NTH-VALUE NTHCDR NULL NUMBER NUMBERP
 NUMERATOR NUNION ODDP OPEN OPEN-STREAM-P OPTIMIZE OR OTHERWISE OUTPUT-STREAM-P
 PACKAGE PACKAGE-ERROR PACKAGE-ERROR-PACKAGE PACKAGE-NAME PACKAGE-NICKNAMES
 PACKAGE-SHADOWING-SYMBOLS PACKAGE-USE-LIST PACKAGE-USED-BY-LIST PACKAGEP
 PAIRLIS PARSE-ERROR PARSE-INTEGER PARSE-NAMESTRING PATHNAME PATHNAME-DEVICE
 PATHNAME-DIRECTORY PATHNAME-HOST PATHNAME-MATCH-P PATHNAME-NAME PATHNAME-TYPE
 PATHNAME-VERSION PATHNAMEP PEEK-CHAR PHASE PI PLUSP POP POSITION POSITION-IF
 POSITION-IF-NOT PPRINT PPRINT-DISPATCH PPRINT-EXIT-IF-LIST-EXHAUSTED
 PPRINT-FILL PPRINT-INDENT PPRINT-LINEAR PPRINT-LOGICAL-BLOCK PPRINT-NEWLINE
 PPRINT-POP PPRINT-TAB PPRINT-TABULAR PRIN1 PRIN1-TO-STRING PRINC
 PRINC-TO-STRING PRINT PRINT-NOT-READABLE PRINT-NOT-READABLE-OBJECT
 PRINT-OBJECT PRINT-UNREADABLE-OBJECT PROBE-FILE PROCLAIM PROG PROG* PROG1
 PROG2 PROGN PROGRAM-ERROR PROGV PROVIDE PSETF PSETQ PUSH PUSHNEW QUOTE RANDOM
 RANDOM-STATE RANDOM-STATE-P RASSOC RASSOC-IF RASSOC-IF-NOT RATIO RATIONAL
 RATIONALIZE RATIONALP READ READ-BYTE READ-CHAR READ-CHAR-NO-HANG
 READ-DELIMITED-LIST READ-FROM-STRING READ-LINE READ-PRESERVING-WHITESPACE
 READ-SEQUENCE READER-ERROR READTABLE READTABLE-CASE READTABLEP REAL REALP
 REALPART REDUCE REINITIALIZE-INSTANCE REM REMF REMHASH REMOVE
 REMOVE-DUPLICATES REMOVE-IF REMOVE-IF-NOT REMOVE-METHOD REMPROP RENAME-FILE
 RENAME-PACKAGE REPLACE REQUIRE REST RESTART RESTART-BIND RESTART-CASE
 RESTART-NAME RETURN RETURN-FROM REVAPPEND REVERSE ROOM ROTATEF ROUND
 ROW-MAJOR-AREF RPLACA RPLACD SAFETY SATISFIES SBIT SCALE-FLOAT SCHAR SEARCH
 SECOND SEQUENCE SERIOUS-CONDITION SET SET-DIFFERENCE
 SET-DISPATCH-MACRO-CHARACTER SET-EXCLUSIVE-OR SET-MACRO-CHARACTER
 SET-PPRINT-DISPATCH SET-SYNTAX-FROM-CHAR SETF SETQ SEVENTH SHADOW
 SHADOWING-IMPORT SHARED-INITIALIZE SHIFTF SHORT-FLOAT SHORT-FLOAT-EPSILON
 SHORT-FLOAT-NEGATIVE-EPSILON SHORT-SITE-NAME SIGNAL SIGNED-BYTE SIGNUM
 SIMPLE-ARRAY SIMPLE-BASE-STRING SIMPLE-BIT-VECTOR SIMPLE-BIT-VECTOR-P
 SIMPLE-CONDITION SIMPLE-CONDITION-FORMAT-ARGUMENTS
 SIMPLE-CONDITION-FORMAT-CONTROL SIMPLE-ERROR SIMPLE-STRING SIMPLE-STRING-P
 SIMPLE-TYPE-ERROR SIMPLE-VECTOR SIMPLE-VECTOR-P SIMPLE-WARNING SIN
 SINGLE-FLOAT SINGLE-FLOAT-EPSILON SINGLE-FLOAT-NEGATIVE-EPSILON SINH SIXTH
 SLEEP SLOT-BOUNDP SLOT-EXISTS-P SLOT-MAKUNBOUND SLOT-MISSING SLOT-UNBOUND
 SLOT-VALUE SOFTWARE-TYPE SOFTWARE-VERSION SOME SORT SPACE SPECIAL
 SPECIAL-OPERATOR-P SPEED SQRT STABLE-SORT STANDARD STANDARD-CHAR
 STANDARD-CHAR-P STANDARD-CLASS STANDARD-GENERIC-FUNCTION STANDARD-METHOD
 STANDARD-OBJECT STEP STORAGE-CONDITION STORE-VALUE STREAM STREAM-ELEMENT-TYPE
 STREAM-ERROR STREAM-ERROR-STREAM STREAM-EXTERNAL-FORMAT STREAMP STRING
 STRING-CAPITALIZE STRING-DOWNCASE STRING-EQUAL STRING-GREATERP
 STRING-LEFT-TRIM STRING-LESSP STRING-NOT-EQUAL STRING-NOT-GREATERP
 STRING-NOT-LESSP STRING-RIGHT-TRIM STRING-STREAM STRING-TRIM STRING-UPCASE
 STRING/= STRING< STRING<= STRING= STRING> STRING>= STRINGP STRUCTURE
 STRUCTURE-CLASS STRUCTURE-OBJECT STYLE-WARNING SUBLIS SUBSEQ SUBSETP SUBST
 SUBST-IF SUBST-IF-NOT SUBSTITUTE SUBSTITUTE-IF SUBSTITUTE-IF-NOT SUBTYPEP
 SVREF SXHASH SYMBOL SYMBOL-FUNCTION SYMBOL-MACROLET SYMBOL-NAME SYMBOL-PACKAGE
 SYMBOL-PLIST SYMBOL-VALUE SYMBOLP SYNONYM-STREAM SYNONYM-STREAM-SYMBOL T
 TAGBODY TAILP TAN TANH TENTH TERPRI THE THIRD THROW TIME TRACE
 TRANSLATE-LOGICAL-PATHNAME TRANSLATE-PATHNAME TREE-EQUAL TRUENAME TRUNCATE
 TWO-WAY-STREAM TWO-WAY-STREAM-INPUT-STREAM TWO-WAY-STREAM-OUTPUT-STREAM TYPE
 TYPE-ERROR TYPE-ERROR-DATUM TYPE-ERROR-EXPECTED-TYPE TYPE-OF TYPECASE TYPEP
 UNBOUND-SLOT UNBOUND-SLOT-INSTANCE UNBOUND-VARIABLE UNDEFINED-FUNCTION
 UNEXPORT UNINTERN UNION UNLESS UNREAD-CHAR UNSIGNED-BYTE UNTRACE UNUSE-PACKAGE
 UNWIND-PROTECT UPDATE-INSTANCE-FOR-DIFFERENT-CLASS
 UPDATE-INSTANCE-FOR-REDEFINED-CLASS UPGRADED-ARRAY-ELEMENT-TYPE
 UPGRADED-COMPLEX-PART-TYPE UPPER-CASE-P USE-PACKAGE USE-VALUE
 USER-HOMEDIR-PATHNAME VALUES VALUES-LIST VARIABLE VECTOR VECTOR-POP
 VECTOR-PUSH VECTOR-PUSH-EXTEND VECTORP WARN WARNING WHEN WILD-PATHNAME-P
 WITH-ACCESSORS WITH-COMPILATION-UNIT WITH-CONDITION-RESTARTS
 WITH-HASH-TABLE-ITERATOR WITH-INPUT-FROM-STRING WITH-OPEN-FILE
 WITH-OPEN-STREAM WITH-OUTPUT-TO-STRING WITH-PACKAGE-ITERATOR
 WITH-SIMPLE-RESTART WITH-SLOTS WITH-STANDARD-IO-SYNTAX WRITE WRITE-BYTE
 WRITE-CHAR WRITE-LINE WRITE-SEQUENCE WRITE-STRING WRITE-TO-STRING Y-OR-N-P
 YES-OR-NO-P ZEROP)
CL-USER>

OBLIST returns a list of all symbols. You can process this list programatically as you would any other list. For example, you could pretty-print it: (pprint (oblist)). We will process this list in the function OBLIST-WITH-CELLS below.

Learning more about symbols with the ?X functions

So now you have a list of all symbols with OBLIST. What’s the next logical step? Right! You pick a symbol, and let Lisp describe it further. To do this, we first write some wrappers around the ANSI Common Lisp functions DESCRIBE and DOCUMENTATION to save us some typing:

;;; The ?X functions retrieve some informations about specific symbols
 
(defun ?? (some-symbol)
"Verbosely describe a symbol using #'describe"
(describe some-symbol))
 
(defun ?f (some-function)
"Documentation string of a function"
(documentation some-function 'function))
 
(defun ?v (some-variable)
"Documentation string of a variable"
(documentation some-variable 'variable))
 
(defun ?t (some-type)
(documentation some-type 'type))
 
(defun ?s (some-structure)
(documentation some-structure 'structure))

Okay, here they are. Now let’s try to learn more about an arbitrary symbol, say CAR:

CL-USER> (?? 'car)
COMMON-LISP:CAR
  [symbol]
 
CAR names a compiled function:
  Lambda-list: (LIST)
  Declared type: (FUNCTION (LIST) (VALUES T &OPTIONAL))
  Documentation:
    Return the 1st object in a list.
  Source file: SYS:SRC;CODE;LIST.LISP
 
(SETF CAR) names a compiled function:
  Lambda-list: (G52694 G52695)
  Derived type: (FUNCTION (T LIST) (VALUES T &OPTIONAL))
  Inline proclamation: INLINE (inline expansion available)
  Source file: SYS:SRC;CODE;SETF-FUNS.LISP
 
(SETF CAR) has setf-expansion: SB-KERNEL:%RPLACA
; No value
CL-USER>

What you see here is the output of ??, our DESCRIBE wrapper, applied on the symbol CAR. Remember to quote ??‘s arguments: you want to pass the symbol itself, not its value! This output has been written to the standard output stream.

While ?? provides a detailed human-readable description of a symbol, this description isn’t easily machine-readable. To make matters worse, the output varies considerably across Common Lisp implementations. For example, the description of CAR above was from Steel Bank Common Lisp (sbcl). On it’s ancestor CMU Common Lisp (cmucl), the description is:

CL-USER> (?? 'car)
 
CAR is an external symbol in the COMMON-LISP package.
Function: #<Function CAR {100B4DC9}>
Function arguments:
  (list)
Function documentation:
  Returns the 1st object in a list.
Its declared argument types are:
  (LIST)
Its result type is:
  T
On Thursday, 4/23/09 03:28:55 am [-2] it was compiled from:
target:code/list.lisp
  Created: Tuesday, 5/10/05 07:58:06 pm [-2]
  Comment: $Header: /var/CVS-REPO/www-admin/farid.hajji.name/blog-repo/ansi-common-lisp-introspection,v 1.9 2013/03/23 12:13:14 farid Exp $
CL-USER>

As you can see, it’s already different, even though sbcl and cmucl share most of the same code base.

Other ANSI Common Lisp implementations provide DESCRIBE as well, but, you may have expected it by now, format its output in an implementation dependend manner. For example, on Clozure Common Lisp (ccl), it looks differently:

CL-USER> (?? 'car)
CAR
Type: SYMBOL
Class: #<BUILT-IN-CLASS SYMBOL>
Function
EXTERNAL in package: #<Package "COMMON-LISP">
Print name: "CAR"
Value: #<Unbound>
Function: #<Compiled-function CAR #x3000000F77CF>
Arglist: (CCL::X)
Plist: NIL
; No value
CL-USER>

You see, it’s terser. And under Armed Bear Common Lisp (abcl), an ANSI Common Lisp written in Java and running on a JavaVM, its output is terser still:

CL-USER> (?? 'car)
CAR is an external symbol in the COMMON-LISP package.
Its function binding is #<FUNCTION CAR {1AFDC98D}>.
The function's lambda list is:
  (list)
The symbol's property list contains these indicator/value pairs:
  JVM::P2-HANDLER JVM::P2-CAR
  SYSTEM:FUNCTION-RESULT-TYPE T
  SYSTEM:SETF-INVERSE SYSTEM:SET-CAR
; No value
CL-USER>

Under Embedded Common Lisp (ecl), a Lisp that compiles its functions by translating them into C and calling a C compiler behind the scenes, the output of DESCRIBE (and therefore ??) looks different again:

CL-USER> (?? 'car)
 
CAR - external symbol in COMMON-LISP package
-----------------------------------------------------------------------------
CAR                                                                [Function]
Function in COMMON-LISP package:
Args: (X)
 
Returns the car of X if X is a cons.  Returns NIL if X is NIL.
-----------------------------------------------------------------------------
CAR                                                                    [Setf]
 
Defined as: (DEFSETF CAR . #<compiled-function 0000000000b81ec0>)
See the doc of DEFSETF.
-----------------------------------------------------------------------------
 
; No value
CL-USER>

And then there’s CLISP (clisp), a popular Lisp that compiles functions to byte-code instead of native code, has yet again a different description for the same symbol:

CL-USER> (?? 'car)
 
CAR is the symbol CAR, lies in #<PACKAGE COMMON-LISP>, is accessible in 18
packages CLOS, COMMON-LISP, COMMON-LISP-USER, EXPORTING, EXT, FFI, MONITOR,
POSIX, PXREF, READLINE, REGEXP, SCREEN, SWANK, SWANK-BACKEND, SWANK-LOADER,
SWANK-MATCH, SWANK-RPC, SYSTEM, names a function, has 3 properties
SYSTEM::INSTRUCTION, SYSTEM::SETF-EXPANDER, SYSTEM::DOC
;; connecting to "http://www.ai.mit.edu/projects/iiip/doc/CommonLISP/HyperSpec/Data/Map_Sym.txt"...connected...HTTP/1.1 404 Not Found
;; "Date: Fri, 17 Feb 2012 13:22:53 GMT"
;; "Server: Apache/2.2.16 (Debian)"
;; "Content-Length: 333"
;; "Connection: close"
;; "Content-Type: text/html; charset=iso-8859-1"
;; ""
;; "<!DOCTYPE HTML PUBLIC \"-//IETF//DTD HTML 2.0//EN\">"
;; "<html><head>"
;; "<title>404 Not Found</title>"
;; "</head><body>"
;; "<h1>Not Found</h1>"
;; "<p>The requested URL /projects/iiip/doc/CommonLISP/HyperSpec/Data/Map_Sym.txt was not found on this server.</p>"
;; "<hr>"
;; "<address>Apache/2.2.16 (Debian) Server at www.ai.mit.edu Port 80</address>"
;; "</body></html>"
;; connecting to "http://www.ai.mit.edu/projects/iiip/doc/CommonLISP/HyperSpec/Data/Symbol-Table.text"...connected...HTTP/1.1 200 OK...45,322 bytes
;; SYSTEM::GET-CLHS-MAP(#<IO INPUT-BUFFERED SOCKET-STREAM CHARACTER www.ai.mit.edu:80>)...978/978 symbols
.
ANSI-CL Documentation is at
 
;; connecting to "http://clisp.cons.org/impnotes/id-href.map"...connected...HTTP/1.1 301 Moved Permanently --> "http://www.clisp.org/impnotes/id-href.map"
;; connecting to "http://www.clisp.org/impnotes/id-href.map"...connected...HTTP/1.1 200 OK...74,297 bytes
;; SYSTEM::GET-STRING-MAP(#<IO INPUT-BUFFERED SOCKET-STREAM CHARACTER www.clisp.org:80>)...2,004 IDs
;; SYSTEM::ENSURE-IMPNOTES-MAP(#P"/usr/local/lib/clisp/data/Symbol-Table.text")...
WARNING: SYSTEM::ENSURE-IMPNOTES-MAP: invalid id "compile-errors" for symbol
         "EXT:SOURCE-PROGRAM-ERROR"
WARNING: SYSTEM::ENSURE-IMPNOTES-MAP: invalid id "compile-errors" for symbol
         "EXT:SOURCE-PROGRAM-ERROR-DETAIL"
WARNING: SYSTEM::ENSURE-IMPNOTES-MAP: invalid id "compile-errors" for symbol
         "EXT:SOURCE-PROGRAM-ERROR-FORM"
644 IDs
 
For more information, evaluate (SYMBOL-PLIST 'CAR).
 
 #<PACKAGE COMMON-LISP> is the package named COMMON-LISP. It has 2 nicknames
 LISP, CL.
 It imports the external symbols of 1 package CLOS and exports 978 symbols to
 17 packages SWANK, SWANK-RPC, SWANK-MATCH, MONITOR, PXREF, SWANK-BACKEND,
 SWANK-LOADER, READLINE, REGEXP, POSIX, EXPORTING, FFI, SCREEN, CLOS,
 COMMON-LISP-USER, EXT, SYSTEM.
 
 #<SYSTEM-FUNCTION CAR> is a built-in system function.
 Argument list: (#:ARG0)
 For more information, evaluate (DISASSEMBLE #'CAR).
 
Documentation:
CLHS:
"Body/acc_carcm_cdr_darcm_cddddr.html"
SYSTEM::FILE:
((DEFSETF #P"/usr/local/ports/lang/clisp/work/clisp-2.49/src/places.fas" 523
   523))
; No value
CL-USER>

I guess, you’ve got the point by now: every ANSI Common Lisp implementation provides a different output for ??, and this output isn’t really machine readable: it can’t be used further down in a Lisp program.

Sometimes, you don’t need a complete description of a symbol as with ??. Many symbols, including variables and functions can contain a documentation string that can be fetched by the ANSI Common Lisp function DOCUMENTATION, or by our wrappers ?v (docstring of a variable) and ?f (docstring of a function).

Let’s query the documentation string of the function CAR (we know by the description returned by ?? that CAR is a function):

CL-USER> (?f 'car)
"Return the 1st object in a list."
CL-USER>

As you can see, the object returned is a string… and strings can be machine-processed, e.g. stored somewhere. We’ll come back to this shortly.

Let’s query the docstring of a variable. What variables do we have? (oblist) returned a list of all objects, so we simply pick one object from the list (see above) that follows the naming convention for special variables (with dynamic binding). We choose *FEATURES*:

CL-USER> (?v '*FEATURES*)
"a list of symbols that describe features provided by the
   implementation"
CL-USER>

If you’re curious, here’s the value of *FEATURES* on sbcl:

CL-USER> *FEATURES*
(:SWANK :SB-BSD-SOCKETS-ADDRINFO :ASDF2 :ASDF :ANSI-CL :COMMON-LISP :SBCL
 :SB-DOC :SB-TEST :SB-LDB :SB-PACKAGE-LOCKS :SB-UNICODE :SB-EVAL
 :SB-SOURCE-LOCATIONS :IEEE-FLOATING-POINT :X86-64 :UNIX :BSD :ELF :FREEBSD
 :GCC-TLS :GENCGC :STACK-GROWS-DOWNWARD-NOT-UPWARD :C-STACK-IS-CONTROL-STACK
 :LINKAGE-TABLE :COMPARE-AND-SWAP-VOPS :UNWIND-TO-FRAME-AND-CALL-VOP
 :RAW-INSTANCE-INIT-VOPS :STACK-ALLOCATABLE-CLOSURES :STACK-ALLOCATABLE-VECTORS
 :STACK-ALLOCATABLE-LISTS :STACK-ALLOCATABLE-FIXED-OBJECTS :ALIEN-CALLBACKS
 :CYCLE-COUNTER :COMPLEX-FLOAT-VOPS :FLOAT-EQL-VOPS :INLINE-CONSTANTS
 :MEMORY-BARRIER-VOPS :MULTIPLY-HIGH-VOPS :OS-PROVIDES-DLOPEN
 :OS-PROVIDES-DLADDR :OS-PROVIDES-PUTWC :OS-PROVIDES-BLKSIZE-T
 :OS-PROVIDES-SUSECONDS-T :OS-PROVIDES-GETPROTOBY-R :OS-PROVIDES-POLL)
CL-USER>

What’s in a symbol?

A symbol doesn’t contain only its value, it contains a lot more! According to ANSI Common Lisp, a symbol contains at least the following attributes (cells):

  • A name cell which contains the name of the symbol
  • A package cell which contains the home package of the symbol
  • A value cell which contains the value of a symbol (e.g. if the symbol is a variable, its value cell contains its value)
  • A function cell which contains the function object bound to the symbol (in this case, the symbol can be called)
  • A property list (plist) cell which contains the property list associated with that symbol (if any).

A symbol may contain many attributes at the same time: for example, FOO may contain a value and evaluating FOO will return that value; and FOO may define a function at the same time, and thus be called like a function. It may also contain a property list.

To explore the cells of a symbol, we define the following wrappers and functions that use only ANSI Common Lisp and the ?X functions defined above:

;;; The SYMBOL-&gt;XXX functions return the content of specific symbol cells
;;; (See HyperSpec, CLHS: System Class Symbol for the following functions)
 
(defconstant U-VALUE 'unbound "Represents an unbound value")
(defconstant U-PLIST 'unbound "Represents an unbound p-list")
(defconstant U-FUNCTION 'unbound "Represents an unbound function")
 
(defun symbol-&gt;name (symbol)
"Return the NAME of SYMBOL as a STRING"
(symbol-name symbol))
 
(defun symbol-&gt;package (symbol)
"Return the PACKAGE of SYMBOL as a STRING"
(package-name (symbol-package symbol)))
 
(defun symbol-&gt;plist (symbol)
"Return the PLIST of SYMBOL as a PLIST, or U-PLIST if unbound"
(let ((plist (symbol-plist symbol)))
(if plist
plist
U-PLIST)))
 
(defun symbol-&gt;value (symbol)
"Return the VALUE of SYMBOL. If unbound, return U-VALUE"
(if (boundp symbol)
(symbol-value symbol)
U-VALUE))
 
(defun symbol-&gt;function (symbol)
"Return the representation of a function of SYMBOL, or U-FUNCTION"
(if (fboundp symbol)
(symbol-function symbol)
U-FUNCTION))
 
(defun symbol-&gt;cells (symbol)
"Create an alist representing SYMBOL's cells"
(let ((alist ()))
;; optional documentation strings
(when (fboundp symbol) (push (cons 'function-doc (?f symbol)) alist))
(when (boundp symbol) (push (cons 'value-doc (?v symbol)) alist))
 
;; the following are cells of a symbol
(push (cons 'function (symbol-&gt;function symbol)) alist)
(push (cons 'plist (symbol-&gt;plist symbol)) alist)
(push (cons 'value (symbol-&gt;value symbol)) alist)
(push (cons 'package (symbol-&gt;package symbol)) alist)
(push (cons 'name (symbol-&gt;name symbol)) alist)
 
;; return value
alist))

The most important function here is, of course, SYMBOL->CELLS, which returns a (machine-readable) association list of a symbol’s cells. Let’s try it out, first on CAR. Calling SYMBOL->CELLS on sbcl yields:

CL-USER> (symbol->cells 'car)
((NAME . "CAR") (PACKAGE . "COMMON-LISP") (VALUE . UNBOUND) (PLIST . UNBOUND)
 (FUNCTION . #<FUNCTION CAR>)
 (FUNCTION-DOC . "Return the 1st object in a list."))
CL-USER>

What do we see here?

  • We get a list of conses, i.e. an association list.
  • Each cons of the list represents a particular cell of the symbol CAR:
    • The NAME of the symbol CAR is the string "CAR" (you wouldn’t have expected that, would’ve you?)
    • CAR is part of the package whose name is the string "COMMON-LISP" (sure, it’s indeed a COMMON-LISP symbol).
    • CAR contains no value. Try to evaluate it by entering car at the REPL, you’ll get an unbound exception.
    • CAR has no associated property list (PLIST) in sbcl. Keep this in mind, when we try SYMBOL->CELLS on other Lisps.
    • CAR has a FUNCTION cell containing the real function object that performs the operation defined by CAR.
  • Since the function cell contains a function, SYMBOL->CELLS has appended a FUNCTION-DOC cons to the association list, containing the documentation string of this function.

As I’ve just said, different ANSI Common Lisp implementations store different values in the cells of a symbol. Let’s examine CAR again, under other Lisps. Under cmucl, we get:

CL-USER> (symbol->cells 'car)
 
((NAME . "CAR") (PACKAGE . "COMMON-LISP") (VALUE . UNBOUND) (PLIST . UNBOUND)
 (FUNCTION . #<Function CAR {100B4DC9}>)
 (FUNCTION-DOC . "Returns the 1st object in a list."))
CL-USER>

Since sbcl and cmucl share a big common code base, it should come as no surprise that the content of CAR‘s cells look very similar. The only difference was the external representation of the function object, but that’s nothing worth talking about.

Now for ccl. Clozure Common Lisp returns the following alist:

CL-USER> (symbol->cells 'car)
((NAME . "CAR") (PACKAGE . "COMMON-LISP") (VALUE . UNBOUND) (PLIST . UNBOUND)
(FUNCTION . #<Compiled-function CAR #x3000000F77CF>) (FUNCTION-DOC))
CL-USER>

Again, the external representation of the function object is different, but that was to be expected. More interesting is that FUNCTION-DOC doesn’t show up as a cons in dotted list notation as previously, but as a list: (FUNCTION-DOC). The reason is obvious, if you think about it: since CAR is FBOUNDP to a function, SYMBOL->CELLS has appended CAR‘s docstring to the association list. But since ccl doesn’t define a docstring for CAR, the associated string was simply NIL:

CL-USER> (?f 'car)
NIL
CL-USER>

Now on to ecl:

CL-USER> (symbol->cells 'car)
((NAME . "CAR") (PACKAGE . "COMMON-LISP") (VALUE . UNBOUND) (PLIST . UNBOUND)
 (FUNCTION . #<compiled-function CAR>)
 (FUNCTION-DOC . "Function in COMMON-LISP package:
Args: (X)
 
Returns the car of X if X is a cons.  Returns NIL if X is NIL.
"))
CL-USER>

Again, nothing new here. Notice that the docstring spans multiple lines here, but it is still one single string.

Armed Bear CL (abcl) yields:

CL-USER> (symbol->cells 'car)
((NAME . "CAR") (PACKAGE . "COMMON-LISP") (VALUE . UNBOUND)
(PLIST JVM::P2-HANDLER JVM::P2-CAR SYSTEM:FUNCTION-RESULT-TYPE T
       SYSTEM:SETF-INVERSE SYSTEM:SET-CAR)
(FUNCTION . #<FUNCTION CAR {399F5D89}>) (FUNCTION-DOC))
CL-USER>

This is the first time we’ve met an ANSI Common Lisp implementation that puts something in the PLIST cell of CAR:

CL-USER> (assoc 'plist (symbol->cells 'car))
(PLIST JVM::P2-HANDLER JVM::P2-CAR SYSTEM:FUNCTION-RESULT-TYPE T
SYSTEM:SETF-INVERSE SYSTEM:SET-CAR)
CL-USER>

Lisp implementations can, and often do, associate properties to symbols by adding them to a propery list. This propery list is then saved in the PLIST cell of the symbol. A property list is simply a list of key and value pairs, stored one after the other in a list: (key1 value1 key2 value2 ...).

How about clisp? Let’s try it!

CL-USER> (symbol->cells 'car)
((NAME . "CAR") (PACKAGE . "COMMON-LISP") (VALUE . UNBOUND)
 (PLIST SYSTEM::INSTRUCTION 91 SYSTEM::SETF-EXPANDER SYSTEM::%RPLACA
  SYSTEM::DOC
  (SYSTEM::FILE
   ((DEFSETF #P"/usr/local/ports/lang/clisp/work/clisp-2.49/src/places.fas" 523
     523))))
 (FUNCTION . #<SYSTEM-FUNCTION CAR>) (FUNCTION-DOC))
CL-USER>

Here too, clisp has associated properties to the symbol CAR.

Now that we’ve examined an object representing a function, let’s turn our attention to an object acting as a variable. Remember *FEATURES* from above? Here are its cells as an alist as returned by clisp:

CL-USER> (symbol->cells '*FEATURES*)
((NAME . "*FEATURES*") (PACKAGE . "COMMON-LISP")
 (VALUE :SWANK :READLINE :REGEXP :SYSCALLS :I18N :LOOP :COMPILER :CLOS :MOP
  :CLISP :ANSI-CL :COMMON-LISP :LISP=CL :INTERPRETER :SOCKETS :GENERIC-STREAMS
  :LOGICAL-PATHNAMES :SCREEN :FFI :GETTEXT :UNICODE :BASE-CHAR=CHARACTER
  :WORD-SIZE=64 :PC386 :UNIX)
 (PLIST . UNBOUND) (FUNCTION . UNBOUND) (VALUE-DOC))
CL-USER>

The only difference here is that now, the cell VALUE contains the value of *FEATURES*, and the cell FUNCTION shows UNBOUND, i.e. *FEATURES* doesn’t contain a function and thus can’t be called.

A little real introspection

For the sake of fun, let’s introspect the object SYMBOL->CELLS we’ve just defined in different Lisps. Try to interpret the results yourself:

This is sbcl‘s cell representation:

CL-USER> (symbol->cells 'symbol->cells)
((NAME . "SYMBOL->CELLS") (PACKAGE . "COMMON-LISP-USER") (VALUE . UNBOUND)
 (PLIST . UNBOUND) (FUNCTION . #<FUNCTION SYMBOL->CELLS>)
 (FUNCTION-DOC . "Create an alist representing SYMBOL's cells"))
CL-USER>

Have you noticed that PACKAGE is now COMMON-LISP-USER instead of merely COMMON-LISP as in the previous examples? The reason is that SYMBOL->CELLS is a user-defined function here and not part of Common Lisp itself. All user-defined symbols go into the COMMON-LISP-USER package by default (unless we switch packages, of course).

And this is cmucl‘s take on it:

CL-USER> (symbol->cells 'symbol->cells)
((NAME . "SYMBOL->CELLS") (PACKAGE . "COMMON-LISP-USER") (VALUE . UNBOUND)
 (PLIST . UNBOUND)
 (FUNCTION . #<Interpreted Function SYMBOL->CELLS {48029179}>)
 (FUNCTION-DOC . "Create an alist representing SYMBOL's cells"))
CL-USER>

What about ccl?

CL-USER> (symbol->cells 'symbol->cells)
((NAME . "SYMBOL->CELLS") (PACKAGE . "COMMON-LISP-USER")
(VALUE . UNBOUND) (PLIST . UNBOUND)
(FUNCTION . #<Compiled-function SYMBOL->CELLS #x3020009322CF>)
(FUNCTION-DOC . "Create an alist representing SYMBOL's cells"))
CL-USER>

Embedded Common Lisp ecl returns:

CL-USER> (symbol->cells 'symbol->cells)
((NAME . "SYMBOL->CELLS") (PACKAGE . "COMMON-LISP-USER") (VALUE . UNBOUND)
 (PLIST . UNBOUND)
 (FUNCTION . #<bytecompiled-closure #<bytecompiled-function SYMBOL->CELLS>>)
 (FUNCTION-DOC . "Create an alist representing SYMBOL's cells"))
CL-USER>

Armed Bear CL abcl:

CL-USER> (symbol->cells 'symbol->cells)
((NAME . "SYMBOL->CELLS") (PACKAGE . "COMMON-LISP-USER") (VALUE . UNBOUND)
(PLIST SYSTEM::%SOURCE
       (#P"/users/farid/Devel/CommonLisp/introspection.lisp" . 2041))
(FUNCTION . #<FUNCTION SYMBOL->CELLS {170AEB17}>) (FUNCTION-DOC))
CL-USER>

Notice how abcl stores the path of the file containing SYMBOL->CELLS‘s source code in the property list under the implementation-dependent property with the key SYSTEM::%SOURCE. This is, of course, an implementation-specific feature that can’t be relied upon in pure ANSI Common Lisp.

For clisp, I’ll show the whole session, for a reason that will become apparent soon:

CL-USER> (load "introspection.lisp")
;; Loading file introspection.lisp ...
;; Loaded file introspection.lisp
T    
 
CL-USER> (symbol->cells 'symbol->cells)
((NAME . "SYMBOL->CELLS") (PACKAGE . "COMMON-LISP-USER") (VALUE . UNBOUND)
 (PLIST SYSTEM::DEFINITION
  ((DEFUN SYMBOL->CELLS (SYMBOL) "Create an alist representing SYMBOL's cells"
    (LET ((ALIST NIL))
     (WHEN (FBOUNDP SYMBOL) (PUSH (CONS 'FUNCTION-DOC (?F SYMBOL)) ALIST))
     (WHEN (BOUNDP SYMBOL) (PUSH (CONS 'VALUE-DOC (?V SYMBOL)) ALIST))
     (PUSH (CONS 'FUNCTION (SYMBOL->FUNCTION SYMBOL)) ALIST)
     (PUSH (CONS 'PLIST (SYMBOL->PLIST SYMBOL)) ALIST)
     (PUSH (CONS 'VALUE (SYMBOL->VALUE SYMBOL)) ALIST)
     (PUSH (CONS 'PACKAGE (SYMBOL->PACKAGE SYMBOL)) ALIST)
     (PUSH (CONS 'NAME (SYMBOL->NAME SYMBOL)) ALIST) ALIST))
   . #(NIL NIL NIL NIL ((DECLARATION OPTIMIZE DECLARATION))))
  SYSTEM::DOC
  (SYSTEM::FILE
   ((SYSTEM::DEFUN/DEFMACRO
     #P"/users/farid/Devel/CommonLisp/introspection.lisp" 68 83))))
 (FUNCTION .
  #<FUNCTION SYMBOL->CELLS (SYMBOL)
    "Create an alist representing SYMBOL's cells"
    (DECLARE (SYSTEM::IN-DEFUN SYMBOL->CELLS))
    (BLOCK SYMBOL->CELLS
     (LET ((ALIST NIL))
      (WHEN (FBOUNDP SYMBOL) (PUSH (CONS 'FUNCTION-DOC (?F SYMBOL)) ALIST))
      (WHEN (BOUNDP SYMBOL) (PUSH (CONS 'VALUE-DOC (?V SYMBOL)) ALIST))
      (PUSH (CONS 'FUNCTION (SYMBOL->FUNCTION SYMBOL)) ALIST)
      (PUSH (CONS 'PLIST (SYMBOL->PLIST SYMBOL)) ALIST)
      (PUSH (CONS 'VALUE (SYMBOL->VALUE SYMBOL)) ALIST)
      (PUSH (CONS 'PACKAGE (SYMBOL->PACKAGE SYMBOL)) ALIST)
      (PUSH (CONS 'NAME (SYMBOL->NAME SYMBOL)) ALIST) ALIST))>)
 (FUNCTION-DOC . "Create an alist representing SYMBOL's cells"))
CL-USER>

Isn’t that interesting? CLISP stores not only the source code for the function in the property list under the key SYSTEM::DEFINITION, it also stores the path of the source file as a list under the key SYSTEM::DOC. Furthermore, the FUNCTION cell contains the function object, itself as a source code representation that is nearly identical to our own source code.

The reason for this is that SYMBOL->CELLS is not yet compiled: it is stored internally as source code, i.e. as a regular lisp list. That’s why you see its source code in the FUNCTION cell above. Calling this function would mean running it through the interpreter. This can and will be slower than if it were a compiled function.

In other words, CLISP doesn’t auto-compile newly defined functions, unlike what other major ANSI Common Lisp implementations do by default.

Of course, nothing prevents us from compiling SYMBOL->CELLS using COMPILE:

CL-USER> (compile 'symbol->cells)
SYMBOL->CELLS
NIL
NIL
CL-USER>

Now, the cells of SYMBOL->CELLS look a little differently:

CL-USER> (symbol->cells 'symbol->cells)
((NAME . "SYMBOL->CELLS") (PACKAGE . "COMMON-LISP-USER") (VALUE . UNBOUND)
 (PLIST SYSTEM::DEFINITION
  ((DEFUN SYMBOL->CELLS (SYMBOL) "Create an alist representing SYMBOL's cells"
    (LET ((ALIST NIL))
     (WHEN (FBOUNDP SYMBOL) (PUSH (CONS 'FUNCTION-DOC (?F SYMBOL)) ALIST))
     (WHEN (BOUNDP SYMBOL) (PUSH (CONS 'VALUE-DOC (?V SYMBOL)) ALIST))
     (PUSH (CONS 'FUNCTION (SYMBOL->FUNCTION SYMBOL)) ALIST)
     (PUSH (CONS 'PLIST (SYMBOL->PLIST SYMBOL)) ALIST)
     (PUSH (CONS 'VALUE (SYMBOL->VALUE SYMBOL)) ALIST)
     (PUSH (CONS 'PACKAGE (SYMBOL->PACKAGE SYMBOL)) ALIST)
     (PUSH (CONS 'NAME (SYMBOL->NAME SYMBOL)) ALIST) ALIST))
   . #(NIL NIL NIL NIL ((DECLARATION OPTIMIZE DECLARATION))))
  SYSTEM::DOC
  (SYSTEM::FILE
   ((SYSTEM::DEFUN/DEFMACRO
     #P"/users/farid/Devel/CommonLisp/introspection.lisp" 68 83))))
 (FUNCTION . #<COMPILED-FUNCTION SYMBOL->CELLS>)
 (FUNCTION-DOC . "Create an alist representing SYMBOL's cells"))
CL-USER>

If you’ve paid attention, you may have noticed that the FUNCTION cell now contains a #<COMPILED-FUNCTION SYMBOL->CELLS>, i.e. a compiled function object.

Instead of manually compiling a function with COMPILE, we could also have compiled the whole file introspection.lisp into a FASL file (fast loading lisp file) with COMPILE-FILE-PATHNAME and loaded that FASL file instead:

CL-USER> (compile-file-pathname "introspection.lisp"
                                :output-file "introspection.fas")
#P"introspection.fas"
CL-USER> (load "introspection.fas")
;; Loading file introspection.fas ...
;; Loaded file introspection.fas
T
CL-USER>

Now, with that file loaded, let’s query the cells again:

CL-USER> (symbol->cells 'symbol->cells)
((NAME . "SYMBOL->CELLS") (PACKAGE . "COMMON-LISP-USER") (VALUE . UNBOUND)
 (PLIST SYSTEM::DOC
  (SYSTEM::FILE
   ((SYSTEM::DEFUN/DEFMACRO #P"/users/farid/Devel/CommonLisp/introspection.fas"
     68 83))))
 (FUNCTION . #<COMPILED-FUNCTION SYMBOL->CELLS>)
 (FUNCTION-DOC . "Create an alist representing SYMBOL's cells"))
CL-USER>

Again, the FUNCTION cell contains the compiled function, as expected. But now, the source code for the function isn’t stored in the property list PLIST anymore. Instead, there’s a pointer to the FASL file containing its definition.

OBLIST-WITH-CELLS

The last function of introspection.lisp is OBLIST-WITH-CELLS, which returns a list of all cells corresponding to a list of objects or to all objects:

;;; OBLIST-WITH-CELLS is an OBLIST that returns a list of alists (cells)
 
(defun oblist-with-cells (&amp;optional (symbol-list (oblist)))
"Apply SYMBOL-&gt;CELLS on all SYMBOLs in SYMBOL-LIST"
(mapcar #'symbol-&gt;cells symbol-list))

You use this function like this:

CL-USER> (oblist-with-cells (list '?v '?f '*FEATURES*))
(((NAME . "?V") (PACKAGE . "COMMON-LISP-USER") (VALUE . UNBOUND)
  (PLIST . UNBOUND) (FUNCTION . #)
  (FUNCTION-DOC . "Documentation string of a variable"))
 ((NAME . "?F") (PACKAGE . "COMMON-LISP-USER") (VALUE . UNBOUND)
  (PLIST . UNBOUND) (FUNCTION . #)
  (FUNCTION-DOC . "Documentation string of a function"))
 ((NAME . "*FEATURES*") (PACKAGE . "COMMON-LISP")
  (VALUE :SWANK :SB-BSD-SOCKETS-ADDRINFO :ASDF2 :ASDF :ANSI-CL :COMMON-LISP
   :SBCL :SB-DOC :SB-TEST :SB-LDB :SB-PACKAGE-LOCKS :SB-UNICODE :SB-EVAL
   :SB-SOURCE-LOCATIONS :IEEE-FLOATING-POINT :X86-64 :UNIX :BSD :ELF :FREEBSD
   :GCC-TLS :GENCGC :STACK-GROWS-DOWNWARD-NOT-UPWARD :C-STACK-IS-CONTROL-STACK
   :LINKAGE-TABLE :COMPARE-AND-SWAP-VOPS :UNWIND-TO-FRAME-AND-CALL-VOP
   :RAW-INSTANCE-INIT-VOPS :STACK-ALLOCATABLE-CLOSURES
   :STACK-ALLOCATABLE-VECTORS :STACK-ALLOCATABLE-LISTS
   :STACK-ALLOCATABLE-FIXED-OBJECTS :ALIEN-CALLBACKS :CYCLE-COUNTER
   :COMPLEX-FLOAT-VOPS :FLOAT-EQL-VOPS :INLINE-CONSTANTS :MEMORY-BARRIER-VOPS
   :MULTIPLY-HIGH-VOPS :OS-PROVIDES-DLOPEN :OS-PROVIDES-DLADDR
   :OS-PROVIDES-PUTWC :OS-PROVIDES-BLKSIZE-T :OS-PROVIDES-SUSECONDS-T
   :OS-PROVIDES-GETPROTOBY-R :OS-PROVIDES-POLL)
  (PLIST . UNBOUND) (FUNCTION . UNBOUND)
  (VALUE-DOC . "a list of symbols that describe features provided by the
   implementation")))
CL-USER>

Or, if you prefer, you can get a very long list by omitting the list of objects that you want to look at:

CL-USER (oblist-with-cells)
(... a very long list omitted ...)
CL-USER>

If the list doesn’t look pretty, you can format it with the pretty printer PPRINT. Here’s an example using ccl:

CL-USER> (oblist-with-cells (list '?v '?f))
(((NAME . "?V") (PACKAGE . "COMMON-LISP-USER") (VALUE . UNBOUND) (PLIST . UNBOU\
ND) (FUNCTION . #<Compiled-function ?V #x30200080D8DF>) (FUNCTION-DOC . "Docume\
ntation string of a variable")) ((NAME . "?F") (PACKAGE . "COMMON-LISP-USER") (\
VALUE . UNBOUND) (PLIST . UNBOUND) (FUNCTION . #<Compiled-function ?F #x3020008\
0DC3F>) (FUNCTION-DOC . "Documentation string of a function")))
 
CL-USER> (pprint (oblist-with-cells (list '?v '?f)))
 
(((NAME . "?V") (PACKAGE . "COMMON-LISP-USER") (VALUE . UNBOUND)
  (PLIST . UNBOUND) (FUNCTION . #<Compiled-function ?V #x30200080D8DF>)
  (FUNCTION-DOC . "Documentation string of a variable"))
 ((NAME . "?F") (PACKAGE . "COMMON-LISP-USER") (VALUE . UNBOUND)
  (PLIST . UNBOUND) (FUNCTION . #<Compiled-function ?F #x30200080DC3F>)
  (FUNCTION-DOC . "Documentation string of a function"))); No value
CL-USER>

Further reading

You may want to read about the ANSI Common Lisp function INSPECT, and check out the introspections of the SLIME ide for further ideas. Of course, you can also look at the source code of major ANSI Common Lisp implementations’ introspection functions like DESCRIBE and friends to see how they get at the internals of a symbol.

The file introspection.lisp

All functions above are defined in the file introspection.lisp below. You can use these functions by calling (LOAD "introspection.lisp") in your own programs or at the read-eval-print loop (REPL).

;;;; introspection.lisp -- functions to inspect ANSI Common Lisp environment
 
;;;; License: 2-clauses BSD
;;
;; Copyright (c) 2012 Farid Hajji. All rights reserved.
;;
;; Redistribution and use in source and binary forms, with or without
;; modification, are permitted provided that the following conditions
;; are met:
;; 1. Redistributions of source code must retain the above copyright
;; notice, this list of conditions and the following disclaimer.
;; 2. Redistributions in binary form must reproduce the above copyright
;; notice, this list of conditions and the following disclaimer in the
;; documentation and/or other materials provided with the distribution.
;;
;; THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
;; ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
;; IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
;; ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
;; FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
;; DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
;; OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
;; HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
;; LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
;; OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
;; SUCH DAMAGE.
;;;;
 
;;; OBLIST returns a list of all available symbols
 
(defun oblist (&amp;optional (packagename "COMMON-LISP-USER"))
"Return a list of all symbols in PACKAGENAME"
(let ((the-symbols ()))
;; DO-SYMBOLS is a common-lisp function
(do-symbols (var packagename)
(setf the-symbols (cons var the-symbols)))
(setf the-symbols (sort the-symbols #'string-lessp))
the-symbols))
 
;;; The ?X functions retrieve some informations about specific symbols
 
(defun ?? (some-symbol)
"Verbosely describe a symbol using #'describe"
(describe some-symbol))
 
(defun ?f (some-function)
"Documentation string of a function"
(documentation some-function 'function))
 
(defun ?v (some-variable)
"Documentation string of a variable"
(documentation some-variable 'variable))
 
(defun ?t (some-type)
(documentation some-type 'type))
 
(defun ?s (some-structure)
(documentation some-structure 'structure))
 
;;; The SYMBOL-&gt;XXX functions return the content of specific symbol cells
;;; (See HyperSpec, CLHS: System Class Symbol for the following functions)
 
(defconstant U-VALUE 'unbound "Represents an unbound value")
(defconstant U-PLIST 'unbound "Represents an unbound p-list")
(defconstant U-FUNCTION 'unbound "Represents an unbound function")
 
(defun symbol-&gt;name (symbol)
"Return the NAME of SYMBOL as a STRING"
(symbol-name symbol))
 
(defun symbol-&gt;package (symbol)
"Return the PACKAGE of SYMBOL as a STRING"
(package-name (symbol-package symbol)))
 
(defun symbol-&gt;plist (symbol)
"Return the PLIST of SYMBOL as a PLIST, or U-PLIST if unbound"
(let ((plist (symbol-plist symbol)))
(if plist
plist
U-PLIST)))
 
(defun symbol-&gt;value (symbol)
"Return the VALUE of SYMBOL. If unbound, return U-VALUE"
(if (boundp symbol)
(symbol-value symbol)
U-VALUE))
 
(defun symbol-&gt;function (symbol)
"Return the representation of a function of SYMBOL, or U-FUNCTION"
(if (fboundp symbol)
(symbol-function symbol)
U-FUNCTION))
 
(defun symbol-&gt;cells (symbol)
"Create an alist representing SYMBOL's cells"
(let ((alist ()))
;; optional documentation strings
(when (fboundp symbol) (push (cons 'function-doc (?f symbol)) alist))
(when (boundp symbol) (push (cons 'value-doc (?v symbol)) alist))
 
;; the following are cells of a symbol
(push (cons 'function (symbol-&gt;function symbol)) alist)
(push (cons 'plist (symbol-&gt;plist symbol)) alist)
(push (cons 'value (symbol-&gt;value symbol)) alist)
(push (cons 'package (symbol-&gt;package symbol)) alist)
(push (cons 'name (symbol-&gt;name symbol)) alist)
 
;; return value
alist))
 
;;; OBLIST-WITH-CELLS is an OBLIST that returns a list of alists (cells)
 
(defun oblist-with-cells (&amp;optional (symbol-list (oblist)))
"Apply SYMBOL-&gt;CELLS on all SYMBOLs in SYMBOL-LIST"
(mapcar #'symbol-&gt;cells symbol-list))
 
;;; That's all, folks!

4 Comments

  1. ernst

    Hi,

    quite OT, are there still plans for a new release of the Perl Book?

     
  2. Hello,

    thank you for asking.

    There won’t be any new editions of the Perl Book anytime soon. My motivation to update it (or the Python Book) is at an all times low.

    Sorry about that.

     
  3. ernst

    Hi Farid,

    I understand that writing books can be a quite ungrateful business, regarding both commercial success and personal satisfaction. On the other hand the books you’ve written are really cool, and while the Python book is still available, the Perl book has been out of print for years now. Note that I don’t think you should add a lot of new stuff, just updating everything to current Perl version and libraries for a reprint. Maybe you could find a co-author doing the necessary changes. I’m wondering, am I the only one pleading for a reprint?

    Slightly ot, your Python book was registered at novelrank.com (absolutely free service, which tracks amazon sales ranks and calculates sales numbers from differences of sales ranks) and seems to be selling somewhat ok, see http://www.novelrank.com/asin/3827325439 . One probably can’t expect a programming book to become a bestseller.

    Though our personal backgrounds may be very different, I’d like to assure you, that this society and the neolib system is dragging down everybody, not just you. A lot of people just try to ignore all the contradictions and discrepancies, some take drugs, some try to raise themselves by despising ‘weaker’ people etc. Personally I’m thinking, that the system will need to go completely bankrupt, before things will start improving again. The whole situation is annoying, because even if you believe in the so-called markets, you’d have to state, that in a real “Free Market(tm)” there would be no such thing as a bailout, ESM, EFSF, etc, at least not without fair compensation for the tax payer. Even the Quantitative Easing of the FED is more responsible than the EU bailouts, no matter what experts say. It’s sad to say, the FED policy of printing money to buy US bonds directly will prevail over the ECB printing money for the banksters in the weak hope that they will buy Euro bonds instead of doing more financial mischief, the whole european austerity strategy will fail. For some reasons the EU elites always want to have one more level of indirection or middle men aka rip-off artists (cf. Ein-Euro-Jobs etc). Another important issue that needs to be mentioned in that context would be closing down all that tax evasion stuff like Double Irish, Dutch Sandwich, Cayman Islands etc, finally establishing some kind of Tobin Tax, but it might need a few more really big crashes until the elites will become reasonable again.

    Ok, enough negative stuff for now, in one or another way life will go on.

    kind regards, ernst

     
  4. ernst

    Hi, it’s me again, sorry for my last post beeing quite offtopic.

    I’m currently trying to refresh my Haskell knowledge, using Thompsons “Haskell craft of functional programming”. I had a medium-level understanding of Haskell when studying, and a minimum knowledge of Lisp, but have to admit, that I forgot most of that stuff. My motivation for refreshing Haskell is a Haskell program, that calculates some boolean formulas in a symbolic way, but at some point switches to concrete values, using the same functions, but switching the way, how functions are evaluated by Haskell. I’d like to use that functions for a similar task in my own program, but it is still too sophisticated for me (at the moment).

    It’s understood that Haskell and Lisp are quite different in most aspects, though both need “thinking in lists” and similar concepts. I’m planning on refreshing my Lisp knowledge in maybe a year or so, and I’d like to choose a book suited for self-study and work with it, what do you think of a book like “Land of Lisp”, available both in English and German?

    kind regards, ernst