The name Lisp, which originally was spelled with upper case letters (LISP), derives from LISt Processor.
The source code of a Lisp program consists of lists.
A list contains atoms or other lists. These elements are put within parenthesis and separated with commas.
Unless instructed otherwise, a list triggers a function call, the first argument being the name of the function.
car / cdr (functions)
car
evaluates to the first element in a list.
* (car '(a b c))
A
* (car '( (a b c) d e f))
(A B C)
* (car '())
NIL
* (car (cons (cons 1 2) (cons 3 4)))
(1 . 2)
cdr
evaluates to the second element in a list (in the liturature typically referred to as «the rest»)
* (cdr (cons (cons 1 2) (cons (cons 3 4) 5)))
((3 . 4) . 5)
* (cdr '(A B C D))
(B C D)
car stands for Contents of the Address part of the Register number, cdr for Contents of the Decrement part of the Register numer.
The «register» in these terms refered to words(?) (x bytes?) in memory, not to registers on the CPU as understood today.
The full contents of a register number (i.e. car and cdr) can be used to represent a cons cell.
car
and cdr
belong to McCarthy's five elementary functions.
List:
* (car '(one two three four five))
ONE
* (cadr '(one two three four five))
TWO
* (caddr '(one two three four five))
THREE
* (cadddr '(one two three four five))
FOUR
List of lists:
* (caar '((one two three) (1 2 3)))
ONE
* (cadar '((one two three) (1 2 3)))
TWO
* (caddar '((one two three) (1 2 3)))
THREE
* (cdar '((one two three) (1 2 3)))
(TWO THREE)
* (cadr '((one two three) (1 2 3)))
(1 2 3)
* (caadr '((one two three) (1 2 3)))
1
* (cadadr '((one two three) (1 2 3)))
2
lambda
The common lisp manual says that the macro lambda
is a dubious shortcut for (function (lambda ...))
or #'(lambda ...)
- but offers no explanation as to why that is:
* (macroexpand '(lambda (x) (x)) )
#'(LAMBDA (X) (X))
T
A labmda expression can be thought of as a name of a function which appears as the first element in a list, giving raise to the following anonymous use of a lambda
:
* (
(lambda (x) (* 3 x))
14
)
42
Combining defun
with lambda
:
* (defun twice (n)
(
(lambda (x) (* 2 x)) n
)
)
TWICE
* (twice 21)
42
Multiple parameters
* ( (lambda (x y z) (* z y x)) 7 3 2)
42
With SBCL, the type of a lambda expression is COMPILED-FUNCTION
. In CLISP, it is just FUNCTION
.
* (type-of (lambda (x) (* 3 x)) )
COMPILED-FUNCTION
Because a function that is defined with a lambda-expression has no name, this function cannot refer to itself.
Hence, lambda
cannot be used to create recursive functions.
let, let*, flet
* (let (
(x "hello")
(y "world")
)
(concatenate 'string x " " y)
)
"hello world"
In a let
expression, the value of a newly defined variable cannot depend on the value of another newly defined variable, thus the following expression throws an error:
* (let (
(x 21 )
(y (* x 3))
)
(print (- y x))
)
However, with let*
, assigning values in sequence is possible:
* (let* (
(x 21 )
(y (* x 3))
)
(print (- y x))
)
42
42
Share a (hidden) variable between two functions (See Paul Graham - On Lisp - 2.6. Closures):
* (let ((counter 0))
(defun new-id () (incf counter ))
(defun reset-id () (setq counter 0))
)
RESET-ID
* (new-id)
1
* (new-id)
2
* (reset-id)
0
* (new-id)
1
flet
names local functions:
* (flet (
( f (x)
(print (concatenate 'string "outer f: " x))
(flet (
( f (x)
(print (concatenate 'string "inner f: " x))
)
)
(f "two")
)
)
)
(f "one")
)
"outer f: one"
"inner f: two"
"inner f: two"
labels
is similar to flet
with the difference that a function defined in labels
can be used in the function being defined:
* (labels (
( fib (n)
(
if (<= n 2)
1
(+ (fib (- n 1)) (fib (- n 2)))
)
)
)
(fib 7)
)
Example of using labels
in a function (Graham - On List, p. 3):
* (defun reverse-list (lst)
(labels (
( reverse-local (lst accum)
(if (null lst)
accum
(reverse-local (cdr lst) (cons (car lst) accum ))
)
)
)
(reverse-local lst nil)
)
)
REVERSE-LIST
* (reverse-list '(5 4 3 2 1))
(1 2 3 4 5)
Compare flet
and labels
with macrolet
.
TODO
McCarthy's five elementary functions
atom | Is something atomic? |
eq | Check if two atomic things are equal? |
car | The left part of an S-expression |
cdr | The right part of an S-expression |
cons | Constructs an S-expression from two atoms |
In
The Roots of Lisp, Paul Graham adds the following two «primitives»:
quote
and
cond
(which he names the
Seven Primitive Operators).
An environment that implements only those five (seven?) functions is a programming language.
Because of this simplicity, Steven Russel was able to create (the abstract machine called eval
) in a few days on an IBM 709 computer.
Compare this with say C or what not - but also with the 25 special forms of Lisp.
These five/seven functions (primitives) allow to create 12 additional functions (
but how, defun
is not part of these 5/7), it is possible to create the
universal function eval
which is able to evaluate Lisp in Lisp. These 12 functions are:
null
,
and
,
not
, (
caar, cadr
,
caddr
,
cadar
,
caddar
),
append
,
list,
pair
and
assoc`
This(?) unversal language was already presented by McCarthy himself in chapter 1.6 of the LISP 1.5 Programmer's Manual.
define vs defun
define
is a function that is available in Scheme but not in Common Lisp.
defun
is a function that is available in Common Lisp, but not in scheme.
Scheme:
> (define (twice x) (* x 2))
> (twice 2)
4
Common Lisp (sbcl)
* (defun twice (x) (* x 2))
* (twice 2)
Variables
Common Lisp has two types of variables:
- Ordinary variables, used to name data objects
- Function names, used to name defined functions, macros and special operators
Common Lisp also has two kinds of variables:
- Lexical (or static) variables
- Special (or dynamic) variables (which are preferrably declared with
defvar
). Generally, the names of special variables start and end with *
. See also (proclaim '(special …))
A Function name is either
- a symbol, or
- a list with two elements whose first element is the symbol
setf
and whose second element is a symbol.
Accessing und updating variables
The dynamic value of a variable can be accessed and updated like so:
Accessing | Updating | Updating using setf |
sm | (setq sm new-value) | (setf sm new-value) |
(car ls) | (rplaca ls new-value) | (setf (car ls) new-value) |
(symbol-value sm) | (set sm new-value) | (setf (symbol-value sm) new-value) |
Thus, having setf
makes setq
, rplaca
and set
redundant.
macro-function
macro-function
determines if a given symbol is the name of a macro.
* (if (macro-function 'if ) "if is a macro" "if is not a macro")
"if is not a macro"
* (if (macro-function 'lambda) "lambda is a macro" "lambda is not a macro")
"lambda is a macro"
Special forms
A
special form: a list, other than a macro form, which is a form with special syntax or special evaluation rules or both, possibly manipulating the evaluation environment or control flow or both. The first element of a special form is a
special operator.
Special forms are special because each of them has a special semantics.
Some (all?) predecessors of Common Lisps (such as MacList) had even more special forms. This number was apparently reduced to 25 in Common Lisp because of Kent Pitman.
Scheme has reduced the number of special forms even more.
Special operators
block | Like progn but with the possibility to bail out with return or return-from . See also do and prog . |
catch | See also throw |
declare | Why is it in this list, it is missing here. |
eval-when | |
flet | Define locally named functions. Compare with let |
function | |
go | |
if | |
labels | |
let | Execute a series of forms with specified variables bound to the specified values. Compare with progn and flet . |
let* | Like let but variables are bound in sequence. |
load-time-value | |
locally | |
macrolet | |
multiple-value-call | |
multiple-value-prog1 | |
progn | Evaluate forms in a sequence (think { … } in C. Compare with the prog1 macro, and the let and block special operators. |
progv | Usefule when writing interpreters for languages embedded in Lisp. |
quote | |
return-from | See also the macro return . |
setq | The simple variable assignment statement. |
symbol-macrolet | |
tagbody | |
the | |
throw | See also catch |
unwind-protect | |
What about:
-
and
, or
-
cond
-
defconstant
-
defparameter
(Creates a global variable which, when changed, is considered changing the program, i. e. the value of the variable is a parameter of the program. Compare with defvar
and defconstant
)
-
defun
(whose purpose is to define a named function)
-
defvar
(The recommended way to declare the use of a special variable in a program. Compare with defparameter
and defconstant
)
-
do
-
eval-when
-
go
-
multiple-value-bind
-
multiple-value-call
-
multiple-value-list
-
multiple-value-prog1
-
multiple-value-setq
-
prog*
(which is to prog
as let*
is to let
)
-
sample-special-form
-
tagbody
-
with-open-file
See also special-operator-p
which determines if a symbol globally names a special operator
Read-eval-print loop (REPL
The REPL is typically used to interact with the Lisp interpreter:
- Read a form from an input-source (file, terminal …)
- Evaluate the form
- Print the value to an output sink (terminal, screen, file …)
macroexpand / macroexpand-1
In SBCL:
* (macroexpand '(setf (car x) y))
(SB-KERNEL:%RPLACA X Y)
T
* (defmacro cond_ (&rest clauses)
(when clauses
`(if ,(caar clauses) ; Note to self: backtick
(progn ,@(cdar clauses))
(cond_ ,@(cdr clauses)))))
* (macroexpand '(cond_ (a b) (c d) (e e) (f g)))
(IF A
(PROGN B)
(COND_ (C D) (E E) (F G)))
T
* (defun macroexpand-tree (tree)
(setq tree (macroexpand tree))
(if (atom tree)
tree
(mapcar #'macroexpand-tree tree)))
MACROEXPAND-TREE
* (macroexpand-tree '(cond_ (a b) (c d) (e e) (f g)))
(IF A
(PROGN B)
(IF C
(PROGN D)
(IF E
(PROGN E)
(IF F
(PROGN G)
NIL))))
setf expanders
* (defvar arr (make-array 5 :initial-contents '(zero one two XYZ four)))
ARR
*
(defun arr-elem (n) (aref arr n))
ARR-ELEM
*
(arr-elem 3)
XYZ
*
(setf (arr-elem 3) 'three)
…
("undefined function" THREE 3)
In order to be able to use setf
to set the value of an element in arr
, we use a setf expander.
Note: the first parameter is used for the new value (new-val
).
*
(defun (setf farr-elem) (new-val n)
(setf (aref arr n) new-val)
)
(SETF FARR-ELEM)
*
(setf (farr-elem 3) 'three)
THREE
*
(arr-elem 3)
THREE
By convention, any function named (setf fn)
should return its first argument as its only value, in order to preserve the specification that setf returns its new value.
quote
* (quote (this list is not evaluated))
(THIS LIST IS NOT EVALUATED)
* (quote (A . (B . (C . ()))))
(A B C)
quote
is one of the Paul Graham's seven primitives.
function
* (defun twice (x) (* 2 x) )
* (function twice)
#<FUNCTION TWICE>
* #'TWICE
#<FUNCTION TWICE>
* (function (lambda (x) (* 3 x)))
#<FUNCTION (LAMBDA (X)) {52A4ADDB}>
function-lambda-expression (Recover the source of a defined function)
* (defun fn (a b) (+ a b))
* (function-lambda-expression #'fn)
(LAMBDA (A B) (BLOCK FN (+ A B)))
T
FN
* (function-lambda-expression #'function-lambda-expression)
NIL
T
FUNCTION-LAMBDA-EXPRESSION
* (function-lambda-expression #'does-not-exist)
… error …
Equality predicates (eq etc.)
eq | |
eql | |
equal | |
equalp | Like equal but ignores type differences. The most general function of all. |
eq
is one of McCarthy's five elementary functions.
However, his version of eq
could only compare atoms while common lisp allows to compare any two objects.
* (equalp 5 5.0)
T
* (equal 5 5.0)
NIL
* (let ((A "xyz"))(eq A A))
T
* (let ((A "xyz")(B "xyz")) (eq A B))
NIL
* (let ((A "xyz")(B "xyz")) (eql A B))
NIL
* (let ((A "xyz")(B "xyz")) (equal A B))
T
* (let ((A "xyz")(B "xyz")) (equalp A B))
T
* (eq 255 #xff)
T
* (eq '((A . B) . (C . D))
'((A . B) C . D )
)
NIL
* (equal '((A . B) . (C . D))
'((A . B) C . D )
)
T
* (eq 'g 'h)
NIL
* (eq 'h 'h)
T
* (defvar fn #'print)
FN
* (eq (symbol-value 'fn) (symbol-function 'print))
T
typep, subtypep, type-of
(type-of obj)
never returns nil
because each object has a type.
(typep obj (type-of obj)
always returns t
.
* (type-of ())
NULL
* (type-of '())
NULL
* (type-of 'NIL)
NULL
* (type-of NIL)
NULL
* (type-of T)
BOOLEAN
* (type-of 'T)
BOOLEAN
* (type-of 'XYZ)
SYMBOL
* (type-of '(1 2 3))
CONS
* (type-of 42)
(INTEGER 0 4611686018427387903)
* (type-of 42.99)
SINGLE-FLOAT
* (type-of 42.99L0)
DOUBLE-FLOAT
* (type-of "42.99")
(SIMPLE-ARRAY CHARACTER (5))
* (type-of #'type-of)
COMPILED-FUNCTION
* (type-of (lambda (x) (* 3 x)) )
COMPILED-FUNCTION
* (type-of (type-of NIL))
SYMBOL
* (type-of #\c)
STANDARD-CHAR
* (type-of 10/3)
RATIO
* (type-of (make-array 5))
(SIMPLE-VECTOR 5)
* (type-of *standard-input*)
SYNONYM-STREAM
* (type-of '*standard-input*)
SYMBOL
* (type-of #(a b c d))
(SIMPLE-VECTOR 4)
* (type-of #P"$ this path doesn't exist!")
PATHNAME
* (let (( x 42 )) (type-of x))
(INTEGER 0 4611686018427387903)
* (typep '(a b c) 'cons)
T
* (typep 42 'cons)
NIL
42
is both an integer and and atom.
* (typep 42 'integer)
T
* (typep 42 'atom)
T
Similarly, "text"
is both a string and and atom:
* (typep "text" 'string)
T
* (typep "text" 'atom)
T
Double float vs single float:
* (typep 42.99L0 'double-float)
T
* (typep 42.99L0 'single-float)
NIL
* (type-of (subtypep 'long-float 'float))
BOOLEAN
* (defvar NUM)
NUM
(setq NUM 42)
42
* (type-of NUM)
(INTEGER 0 4611686018427387903)
* (type-of 'NUM)
SYMBOL
* (subtypep 'float 'long-float)
NIL
T
* (subtypep 'long-float 'float)
T
T
See also
-
defstruct
(which creates new types)
-
coerce
-
satisfies
atom, consp
(atom obj) ≡ (typep obj 'atom) ≡ (not (typep obj 'cons))
(consp obJ) ≡ (typep obj 'cons) ≡ (not (typep obj 'atom))
* (atom 42)
T
* (atom '(a b c))
NIL
* (atom '((( ))) )
NIL
* (atom '(((X))) )
NIL
((ONE TWO THREE))
* (consp 42)
NIL
* (consp '(a b c))
T
()
is nil
, so:
* (atom '())
T
* (defvar lst '(a b c))
LST
* (atom lst)
NIL
* (atom 'lst)
T
* (atom 'undefined-symbol)
T
atom
is one of McCarthy's five elementary functions.
* (vectorp #(1 2 3))
T
* (vectorp '(1 2 3))
NIL
(functionp x) ≡ (typep x ’function)
* (functionp #'list)
T
* (functionp #'(lambda (x) (print x)))
T
Printing functions
prin1 | Representation of an object. prin1 is intended to be consumed by read , compare with princ . |
print | Like prin1 except that the printed representation is preceeded by a newline (see terpri ) and followed by a space. |
pprint | Like print except that the trailing space is omitted and the object is printed with the *print-pretty* flag set to nil . Returns no value. |
princ | Like prin1 except that no escape characters are printed. The output of princ is intended to be consumed by humans, compare with prin1 . princ prints a character exactly like write-char |
write-to-string | |
prin1-to-string | |
princ-to-string | |
write-char | Writes a character (and returns it) |
write-string | |
write-line | Compare with read-line |
write-sequence | |
terpri | Writes a newline to the output stream. Identical in effect to (write-char #\Newline output-stream) . Compare with fresh-line |
fresh-line | LIke terpri , but only prints a newline if the stream is not at the start of a line. Returns T or F accordingly. |
finish-output | |
force-output | |
clear-output | |
write-byte | |
write-char
* (write-char #\c)
c
#\c
write
* (write "foo")
"foo"
"foo"
* (write 'foo)
FOO
FOO
* (write 2)
2
2
* (write #'write)
#<FUNCTION WRITE>
#<FUNCTION WRITE>
Number sign
#o77 | Octal value (of an integer?) |
#xff | Hexadecimal value |
#b0011101011 | Binary value |
#\C | The character C |
#(a b c) | Vector |
#'cons | #'fn is to (function fn) as 'xyz is to (quote xyz) |
format
Many format
operations are directly or indirectly defined in terms of prin1
or princ
which are affected by the printer control variables.
~A | Ascii |
~S | S-expression |
~D | Decimal |
~B | Binary |
~O | Octal |
~X | Hexadecimal |
~nR | With given radix n . ~@R and ~:@R produce roman numerals |
~P | Plural |
~C | Character |
~F | Fixed floating point |
~E | Exponential floating point |
~G | General floating point |
~$ | Dollars floating point |
~% | #\Newline . ~n% prints n newlines. See also terpri |
~& | |
~| | Page seperator |
~~ | A tilde |
~T | Tabulate |
~* | Ignore an argument |
~? | Indirection |
~_ | Conditional new line |
~W | Write |
~I | Indent |
~(str~) | Case conversion |
~
can be followed immediately with a «real» newline.
There is also ~[str0 ~;str1 ~;...~;strn~
for conditional expressions (and of course even more).
Common Lisp ed 2, p. 909: All of the existing printing functions (write
, prin1
, print
, princ
, pprint
, write-to-string
, prin1-to-string
, princ-to-string
, the ~S
and ~A
format operations, and the ~B
, ~D
, ~E
, ~F
, ~G
, ~$
, ~O
, ~R
, and ~X
format operations when they encounter a non-numeric value) are required to be changed to go through the print-object
generic function
defstruct
* (defstruct xyz num txt)
XYZ
Behind the scenes, the macro defstruct
created the function make-xyz
:
* (defvar obj)
OBJ
* (setf obj (make-xyz :num 42 :txt "hello world"))
#S(XYZ :NUM 42 :TXT "hello world")
The macro also created the «accessor» functions xyz-num
and xyz-txt
:
* (xyz-num obj)
42
* (xyz-txt obj)
"hello world"
The macro also created the «type» xyz
:
* (type-of obj)
XYZ
* (typep obj 'xyz)
T
* (xyz-p obj)
T
… And also a «copier function»:
* (defvar copy-of-obj)
COPY-OF-OBJ
* (setf copy-of-obj (copy-xyz obj))
#S(XYZ :NUM 42 :TXT "hello world")
Modify struct-objects with setf
:
* (setf (xyz-num copy-of-obj) 99)
99
* copy-of-obj
#S(XYZ :NUM 99 :TXT "hello world")
* obj
#S(XYZ :NUM 42 :TXT "hello world")
See also defclass
.
loop
* (loop for i from 1 to 5 collect i)
(1 2 3 4 5)
concatenate
* (concatenate 'string "hello" " " "world")
"hello world"
make-array
* (make-array 5)
#(0 0 0 0 0)
* (make-array '(2 3))
#2A((0 0 0) (0 0 0))
* (make-array 5 :initial-contents '(3 2 5 4 1))
#(3 2 5 4 1)
:element-type
* (make-array 5 :element-type 'single-float)
#(0.0 0.0 0.0 0.0 0.0)
See also subtypep
.
aref
* (let (( a (make-array 6 :initial-contents '(zero one two three four five)) ))
(aref a 2)
)
TWO
length
* (length "abcd")
4
&optional
In a parameter list (of a function?), all arguments on the right side of &optional
are optional
* (defun ex-1 (param-1 &optional (param-2 "default value"))
(format t "~a, ~a!~%" param-1 param-2))
EX-1
* (ex-1 "hello")
hello, default value!
NIL
* (ex-1 "hello" "world")
hello, world!
NIL
* (defun ex-2 (param-1 &optional param-2)
(if param-2
(format t "~a, ~a!~%" param-1 param-2)
(format t "~a!~%" param-1 )
))
EX-2
* (ex-2 "hello")
hello!
NIL
* (ex-2 "hello" "world")
hello, world!
NIL
(
See also &rest
and &key
.
read
read
is the so-called «Lisp reader»: it reads characters from an input stream and parses them as representations of Lisp objects.
The behavior of read
is controled by readtables.
read &optional input-stream eof-error-p eof-value recursive-p
read
reads in the printed representation of a Lisp object from input-stream, builds a corresponding Lisp object, and returns the object.
read
seems to be associated with the opening paranethesis (which seems to be a macro)
do
* (do ( (i 0 (1+ i)) ) ; start with i = 0, increment i by one
( (>= i 5 ) ) ; end when i is equal or greater than 5
; ( format t "~d~%" i ) ; print i
( print i ) ; print i
)
0
1
2
3
4
NIL
Compare with do*
.
/
* (/ 9 3)
3
* (/ 10 3)
10/3
* (/ 10.0 3)
3.3333
* (* 10/3 3)
10
* (type-of 10/3)
RATIO
multiple-value-bind, values
truncate
returns two values:
* (truncate 12.345)
12
0.34500027
But the following construct compares only the first returned value:
* (= 12 (truncate 12.345))
T
multiple-value-bind
can be used of both values are needed;
* (multiple-value-bind (int frac) (truncate 12.345)
(format t "int = ~d, frac = ~f" int frac)
)
int = 12, frac = 0.34500027
NIL
values
can be used to return multiple values:
* (defun one-two-three ()
(values 1 2 3)
)
ONE-TWO-THREE
* (multiple-value-bind (a b c) (one-two-three)
(print a)
(print b)
(print c)
)
1
2
3
3
describe
* (describe '5)
5
[fixnum]
* (describe '5.5)
5.5
[single-float]
* (describe #'describe)
#<FUNCTION DESCRIBE>
[compiled function]
Lambda-list: (SB-IMPL::OBJECT &OPTIONAL
(SB-KERNEL:STREAM-DESIGNATOR *STANDARD-OUTPUT*))
Declared type: (FUNCTION (T &OPTIONAL (OR STREAM BOOLEAN))
(VALUES &OPTIONAL))
Documentation:
Print a description of OBJECT to STREAM-DESIGNATOR.
Known attributes: unwind, any
Source file: SYS:SRC;CODE;DESCRIBE.LISP
inspect
inspect
is the interactive version of describe
* (format (inspect #'inspect))
The object is a FUNCTION named INSPECT.
0. Lambda-list: (SB-IMPL::OBJECT)
1. Ftype: (FUNCTION (T) (VALUES &OPTIONAL))
* (format (inspect #'inspect))
The object is a FUNCTION named INSPECT.
0. Lambda-list: (SB-IMPL::OBJECT)
1. Ftype: (FUNCTION (T) (VALUES &OPTIONAL))
> (inspect 'inspect)
The object is a SYMBOL.
0. Name: "INSPECT"
1. Package: #<PACKAGE "COMMON-LISP">
2. Value: "unbound"
3. Function: #<FUNCTION INSPECT>
4. Plist: NIL
apropos
* (apropos 'print)
M-expressions
M-expressions can be translated to S-expression.
M-expressions were not implemented in common lisp.
gensym
gensym
creates a variable name that is guaranteed to be unique in the program.
(defmacro swap (a b)
`(let ((tmp ,a))
(setf ,a ,b )
(setf ,b tmp)
)
)
(defvar a 42)
(defvar b 99)
(swap a b)
(print a)
(print b)
(defvar tmp 1)
(swap tmp b)
(print tmp) ; --> Still 1!
(print b ) ; --> Still 2!
The problem is that tmp
is used within the macro and is already a global variable:
* (macroexpand-1 '(swap tmp b))
(LET ((TMP TMP))
(SETF TMP B)
(SETF B TMP))
T
With gensym
, this problem does not occur:
(defmacro swap (a b)
(let ((sym (gensym) ))
`(let ((,sym ,a))
(setf ,a ,b )
(setf ,b ,sym)
)
)
)
(defvar sym 42)
(defvar a 99)
(swap sym a)
(print a)
(print sym)
* (macroexpand-1 '(swap sym a))
(LET ((#:G490 SYM))
(SETF SYM A)
(SETF A #:G490))
T
*
The *
seems to represent the last evaluated value:
* (+ 11 3)
14
* (+ * 2)
16
proclaim
According to the common lisp manual, (proclaim '(optimize speed))
informs the compiler to try to use tail-recursion optimization.
declaim
declaim
is a macro that makes proclamations recognizable at compile time.
Compare with proclaim
and declare
.
declare
* (defun f (x)
(declare (type fixnum x))
(+ x 1)
)
F
* (f 5)
6
* (f 5.1) ; --> Error The value 5.1 is not of type FIXNUM when binding X
SBCL
Types
The SBCL compiler treats types differently (with more comprehensive type checking) than most other Lisp compilers.
Diagnostic messages
(declaim (sb-ext:muffle-conditions sb-ext:compiler-note))
See also Chapter 4.1 in the manual (2.4.8)
sbcl:*core-pathname*
* sb-ext:*core-pathname*
#P"/usr/bin/../lib/sbcl/sbcl.core"
See also the --core
command line option.
sb-kernel:get-lisp-obj-address
In SBCL:
* (sb-kernel:get-lisp-obj-address 42 )
84
* (sb-kernel:get-lisp-obj-address "42")
68745230335
* (sb-kernel:get-lisp-obj-address #'sb-kernel:get-lisp-obj-address)
1386184299
Compare with describe
and inspect
See also
-
find-object-by-address
-
system:address-of
in CLISP.
Quicklisp
$ cd ~
$ curl -O https://beta.quicklisp.org/quicklisp.lisp
$ gpg --verify quicklisp.lisp.asc quicklisp.lisp
$ sbcl --load quicklisp.lisp
…
* (quicklisp-quickstart:install)
* ; (ql:system-apropos "vecto")
* ; (ql:quickload "vecto")
* (ql:add-to-init-file)
I will append the following lines to #P"/home/rene/.sbclrc":
;;; The following lines added by ql:add-to-init-file:
#-quicklisp
(let ((quicklisp-init (merge-pathnames "quicklisp/setup.lisp"
(user-homedir-pathname))))
(when (probe-file quicklisp-init)
(load quicklisp-init)))
Press Enter to continue.
#P"/home/rene/.sbclrc"
(exit)
$ (ql:help)
"For help with Quicklisp, see http://www.quicklisp.org/beta/"
But… I should have installed
Linedit.
Clojure
Clojure does not have dotted pairs.
Commas are considered whitespace.