书籍下载地址:

Ansi Common Lisp 中文版|百度网盘

实用Common.Lisp编程 .pdf|百度网盘

LISP指令速查网站推荐:

Simplified Common Lisp reference (jtra.cz)

我制作的表格:

由于Common LISP命令很多,经常忘,所以做个这个表格,方便速查。

表格中命令的顺序基本为ANSI Common LISP这本书中命令出现的顺序。

命令 含义 例子
T
NIL
+-*/ 加减乘除 > (+ 2 3 4)
9
1+ (1+ n) 相当于 (+ n 1)
1- (1- n) 相当于 (- n 1)
>和< 大于和小于 > (> 2 1)
T
CHAR< 和 CHAR> 字符比较
** 全局变量需要左右加上星号 > (setf *print-array* t)
T
ZEROP 为0时返回真
ACTERP 是否为字符
/= 不相等
= 判断相等(建议到这个网站查看具体解释)。仅能判断数字。 > (= 4 4.0)
 T
EQ 是否完全相同。内容相同但是内存位置不同也为不同。不用于数字。 > (eq (cons ‘a ‘b) (cons ‘a ‘b))
NIL
> (eq ‘a ‘a)
T
EQL 与EQ相似。可以比较数字。
EQUAL 是否内容相同。内存位置可以不同。字符串大小写敏感 > (equal (list 1 (cons 2 3)) (list 1 (cons 2 (+ 2 1))))
T
EQUALP 字符串大小写不敏感
AND OR NOT 逻辑与、或、非
ODDP 是否为奇数
EVENP 是否为偶数
QUOTE(`) 不求值 > `(+ 1 2)
(+ 1 2)
CONS 构建一个长度为2的列表
(但第二个输入值可以是一个列表)
> (cons ‘a ‘(b c d))
(A B C D)
CONSP 判断是否为CONS
LIST 构建一个列表 (list 1 2 3)
GETF 获取列表的键值 (getf (list :a 1 :b 2 :c 3) :a) ;;如果没有该值,返回NIL
CAR 获取列表第一个元素
CDR 获取列表第二个以及
之后的元素构成的列表
THIRD 获取列表第三个元素
LISTP 判断输入是否为列表
NULL 判断是否为空表或NIL
IF 相当于c语言的aaa?xxx:yyy
DEFUN 声明全局函数
(defun name (parameter*))
“Optional documentation string.”
body-form*)
(defun our-third (x)
(car (cdr (cdr x))))
调用时:(our-third (1 2 3))
(DEFUN的参数列表
&rest 剩余的参数。会被包装为列表。 (defun our-funcall (fn &rest args)
(apply fn args))
&optional 可选参数 (defun philosoph (thing &optional (property ‘fun))
(list thing ‘is property))
&key 关键字参数 > (defun keylist (a &key x y z)
(list a x y z))
KEYLIST
> (keylist 1 :y 2)
(1 NIL 2 NIL)
)
EQL 相等判断
FORMAT 输出 > (format t “~A plus ~A equals ~A. ~%” 2 3 (+ 2 3))
2 PLUS 3 EQUALS 5
NIL
~A 数据输出的位置,相当于C语言的%d
~% 换行符
READ 输入 > let ((val (read))
LET 定义局部变量 > (let ((x 1) (y 2))
(+ x y))
3
DEFPARAMETER 创建全局变量(变量需要加星号) > (defparameter *glob* 99)
DEFCONSTANT 定义全局常量(不需要星号)
BOUNDP 判断是否为全局变量或常量 > (boundp ‘*glob*)
T
DEFVAR 定义全局变量 (defvar *db* NIL)
SETQ 赋值
SETF 赋值(可给全局或局部变量),可以创建全局变量。
可以给数组的某个值赋值,而setq不行。
> (let ((a ‘(1 2 3 4))) (setf (third a) ‘new-value) a)
(1 2 NEW-VALUE 4)
SET 赋值。用于设置符号 (set ‘foo ‘(1 2 3))
INCF 自加。不加参数时相当于c的++。也可以参数相当于+=
REMOVE 返回不包含这个对象的新列表,但不改变原列表 > (setf lst ‘(c a r a t))
(C A R A T)
> (remove ‘a lst)
(C R T)
DELETE REMOVE的破坏性版本。但不能保证所需移除的元素都能移除。 > (setf lst ‘(a r a b i a) )
(A R A B I A)
> (delete ‘a lst )
(R B I)
> lst
(A R B I)
DO 循环
(DO (变量定义)
(结束条件 返回值)
循环主体)
其中变量定义为(变量名 变量初值 (变量变化语句))
(defun show-squares (start end)
(do ((i start (+ i 1)))
((> i end) ‘done)
(format t “~A A%” i (* i i))))
DOTIMES 循环次数 (dotimes (x 5 x)
(format t “~A ” x))
0 1 2 3 4
5;; 第一行第二个x是返回值,可以不加
LOOP 循环宏 > (loop for x from 0 to 9
do (princ x))
0123456789
NIL
> (loop for x = 8 then (/ x 2)
until (< x 1)
do (princ x))
8421
NIL
(defun sumx (n)
(loop for x from 1 to n
sum x));;返回从1加到n的结果
> (loop for x from 1 to 5
collect (random 10))
(3 8 6 5 0)
(defun even/odd (ns)
(loop for n in ns
if (evenp n)
collect n into evens
else collect n into odds
finally (return (values evens odds))))
> (even/odd ‘(1 2 3 4))
(2 4)
(1 3)
(loop for i below 10
and a=0 then b
and b=1 then (+ b a)
finally (return a));;计算第11个斐波那契数
PROGN 接受任意数量的表达式,依序对它们求值,并返回最后一个值。
DOLIST for each… > (dolist (obj lst) 相当于C++的for(auto obj:lst){,相当于Python的for obj in lst:
FUNCTION(#’) 把函数当做实参传入
APPLY 接受函数和实参列表,并返回把传入函数应用在后面实参的结果 > (apply #’+ ‘(1 2 3))
6
FUNCALL 功能和APPLY相同,但实参不需要包装成列表。 > (funcall #’+ 1 2 3)
6
LAMBDA Lambda表达式 (lambda (x y)
(+ x y))
> (funcall #'(lambda (x) (+ x 100)) 1)
TYPEP 判断是否为某种类型 > (typep 27 ‘integer)
T
COPY-LIST 返回列表的复制
ATOM 验证一个项是否为原子(即列表的一个项)
APPEND 返回列表串接 > (append ‘(a b) ‘(c d) ‘e)
(A B C D E)
NCONC 返回列表串接并更新第一个列表的最后一个 cons 单元的 next 指针。 > (let ((l1 (list 1 2 3))
(l2 (list 4 5 6)))
(nconc l1 l2)
l1)
(1 2 3 4 5 6)
NTH 通过索引获取列表元素 > (nth 0 ‘(a b c))
A
NTHCDR 找到第n个CDR > (nthcdr 2 `(a b c d e))
(C D E)
LAST 返回列表最后一个CONS对象 > (last ‘(a b c))
(C)
LAST的CAR 返回列表的最后一个元素 > (car (last ‘(a b c))) 
C
SECOND 返回第二个元素
CADR 返回第二个元素(相当于CDR的CAR)
CADDR 返回第三个元素(相当于CDR的CDR的CAR)可以无限加D。
MAPCAR 返回把函数应用到列表每个元素的结果 > (mapcar #'(lambda (x) (+ x 10))
‘(1 2 3))
(11 12 13)
MAPCAN 类似MAPCAR。但它返回值是用NCONC拼接在一起的。
MAPC 把函数应用到列表每个元素,返回原来的列表
MAP 把函数应用到列表每个元素,可定义返回的类型。 (map ‘list (lambda (x) (+ x 10)) ‘(1 2 3 4))
(11 12 13 14)
MAP-INTO 把函数应用到列表每个元素,第一个参数不是一个序列类型,而是用来存储结果的。 > (let ((a (list 1 2 3 4))) (map-into a #’* a a) a)
(1 4 9 16)
还可以:(setf v (map-into v #’1+ v))
MAPLIST 将列表的渐进的下一个 CDR传入函数 > (maplist #'(lambda (x) x) ‘(a b c))
((A B C) (B C) (C))
MEMBER 判断元素是否为列表的成员。可以传入参数:TEST和:KEY > (member ‘b ‘(a b c))
(B C)
> (member ‘(a) ‘((a) (z)) :test #’equal)
((A) (Z))
> (member ‘a ‘((a b) (c d)) :key #’car)
((A B) (C D)) ;;在这个例子里,我们询问是否有一个元素的CAR是 a
MEMBER-IF 返回由满足条件的元素构成的列表 > (member-if #’oddp ‘(2 3 4))
(3 4)
ADJOIN 如果对象还不是列表的,成员,构建对象至列表上 > (adjoin ‘b ‘(a b c))
(A B C)
> (adjoin ‘z ‘(a b c))
(Z A B C)
UNION 并集
INTERSECTION 交集
SET-DIFFERENCE 补集 > (set-difference ‘(a b c d e) ‘(b e))
(A C D)
LENGTH 返回元素的数目
SUBSEQ 获取列表的一部分,相当于其他语言的Slice > (subseq ‘(a b c d) 1 2)
(B)
>(subseq ‘(a b c d) 1)
(B C D)
REVERSE 列表反转
NREVERSE 使原列表反转?
EVERY 判断列表每个元素都满足条件 > (every #’oddp ‘(1 3 5))
T
SOME 判断列表部分元素满足条件 > (some #’evenp ‘(1 2 3))
T
PUSH 把元素插入列表的前端 (push atom list)
POP 移除列表的第一个元素,并返回这个元素
ASSOC 返回列表中CAR为指定元素的列表 > (setf min ‘((a b c) (b c) (c d)))
> (cdr (assoc ‘a min))
(B C)
MAKE-ARRAY 构造数组 > (setf arr (make-array ‘(2 3) :initial-element nil)) ;;构造了一个2×3的数组
AREF 通过索引获取数组元素 > (setf (aref arr 0 0) ‘b)
B>
(aref arr 0 0)
B
#na 表示字面常量的数组,其中n是数组的维度 #2a((b nil nil) (nil nil nil))
VECTOR 向量 > (vector “a” ‘b 3)
VECTOR-PUSH 把元素插入向量的前端
VECTOR-POP 移除向量的第一个元素,并返回这个元素
SVREF 通过索引获取向量元素
WRITE-TO-STRING 数字转字符串
SORT 字符串排序 > (sort “elbow” #’char<)
“below”
CHAR 通过索引获取字符串元素 (char string pos)
COPY-SEQ 返回序列(字符串)的复制
CONCATENATE 连接 > (concatenate ‘string “not ” “to worry”)
“not to worry”
TAILP 如果第一个列表是第二个列表的一部分,则返回T
ELT 通过索引获取任何种类的序列元素。针对特定类型的序列,特定的存取函数会比较快,所以使用 elt 是没有意义的,除非在代码当中,有需要支持通用序列的地方。
POSITION 返回序列中一个元素的位置,未找到元素时返回 nil。参数:start :end :test > (position #\a “fantasia”)
1>
(position #\a “fantasia” :start 3 :end 5)
4
> (position 3 ‘(1 0 7 5) :test #'<)
2
SUBSEQ 获取子串(SUBSEQ STR P1 P2)
POSITION-IF 返回第一个满足此函数的元素 > (position-if #’oddp ‘(2 3 4 5))
1
FIND 返回要寻找的对象 > (find #\a “cat”)
#\a
FIND-IF 返回要寻找的满足函数的对象 > (find-if #’characterp “ham”)
#\h
REMOVE-DUPLICATES 仅保留序列中每个元素的最后一次出现。
REDUCE 把序列压缩成一个值 (reduce #’fn ‘(a b c d))等同于(fn (fn (fn ‘a ‘b) ‘c) ‘d)
DEFSTRUCT 定义结构体 (defstruct point
x
y)
MAKE-HASH-TABL 创建哈希表,无需参数。 > (setf ht (make-hash-table))
GETHASH 获取一个键值 > (setf (gethash ‘color ht) ‘red)
RED
REMHASH 从一个哈希表中移除一个词条,若返回T,说明有词条被移除
BLOCK
RETURN-FROM 返回块或函数 > (block head
(format t “Here we go.”)
(return-from head ‘idea)
(format t “We’ll never see this.”))
Here we go.
IDEA
RETURN 返回
TAGBODY
GO 相当于其他语言的goto。需要在TAGBODY下使用 > (tagbody
(setf x 0)
top
(setf x (+ x 1))
(format t “~A ” x)
(if (< x 10) (go top)))
1 2 3 4 5 6 7 8 9 10
NIL
LET* 相当于嵌套版本的LET,可以依赖一个表达式设立另一个变量。可以把x设为1,同时把y设为x+1.原版LET就不行。
WHEN 当测试为真时,对主体求值
UNLESS 仅在测试表达式返回假时,才对主体求值
CASE 相当于C语言的switch (defun month-length (mon)
(case mon
((jan mar may jul aug oct dec) 31)
((apr jun sept nov) 30)
(feb (if (leap-year) 29 28))
(otherwise “unknown month”)))
TYPECASE 按照类型来switch (TYPECASE X
(NUMBER (* X 2)))
VALUES 返回多个值
MULTIPLE-VALUE-BIND 绑定多个值。如果变量的数量大于数值的数量,剩余的变量会是 nil 。如果数值的数量大於变量的数量,多余的值会被舍弃。
CATCH 捕获异常 (defun super ()
(catch ‘abort
(sub)
(format t “We’ll never see this.”)))
(defun sub ()
(throw ‘abort 99))
> (super)
99
THROW 抛出异常
ERROR 抛出异常文字 (ERROR “Oops!”)
UNWIND-PROTECT 使程序不会被报错打断 (UNWIND-PROTECT
FBOUNDP 是否有函数与给定符号绑定 > (fboundp ‘+)
T
SYMBOL-FUNCTION 返回函数。可用于给函数配置某个名字。 (setf (symbol-function ‘add2)
#'(lambda (x) (+ x 2)))
> (add2 1)
3
DOCUMENTATION 获取函数的文档字串 > (DOCUMENTATION #’+ ‘function)
“sum of its arguments. With no args, returns 0.”
LABELS 声明局部函数。用法与DEFUN一样。
COND 直到某个条件为真时才返回。相当于嵌套if或switch > (cond ((> 3 4) “variant 1”)
((> 4 2) “variant 2”)
(t “always valid variant”))
“variant 2”
DECLARE(SPECIAL x) 使x为动态作用域(详见ANSI COMMON LISP 76页)
COMPILED-FUNCTION-P 检查函数是否已被编译
COMPILE 编译函数
COMPILE-FILE 编译文件
MAKE-PATHNAME 新建一个路径。参数有host, device, directory, name, type 以及 version > (setf path (make-pathname :name “myfile”))
OPEN 打开文件流。需要一个路径和大量选择性关键字参数。 > (setf str (open path :direction :output :if-exists :supercede)) ;;supercede表示取代。output表示写文件。input表示读文件。
CLOSE 关闭文件
READ-LINE 从文件流中读一行。若不指定文件流,则从标准输入中读一行,相当于READ。
WITH-OPEN-FILE 相当于Python的with,不需要close,保证文件能够关闭。 (with-open-file (str path :direction :output
:if-exists :supercede)
(format str “Something~%”));;向文件写入Something\n
PRIN1 输出包含双引号。给程序产生输出。
PRINC 输出不包含双引号。给人类产生输出。
SYMBOL-NAME 获取符号名 > (symbol-name ‘abc)
“ABC”
垂直杠之间的字符序列将被视为符号。
SYMBOL-PLIST 获取符号的属性列表(PLIST) > (setf (get ‘alizarin ‘color) ‘red)
RED
> (get ‘alizarin ‘color)
RED
> (setf (get ‘alizarin ‘transparency) ‘high)
HIGH
> (symbol-plist ‘alizarin)
(TRANSPARENCY HIGH COLOR RED)
DEFPACKAGE 定义包 (defpackage “MY-APPLICATION”
(:use “COMMON-LISP” “MY-UTILITIES”)
(:nicknames “APP”)
(:export “WIN” “LOSE” “DRAW”))
(in-package my-application)
这段代码定义了新包my-application,使用了两个包,COMMON-LISP和MY-UTILITIES,一个昵称为APP,这样背的包可以这样引用符号APP:WIN。包本身只输出三个符号”WIN”、”LOSE”和”DRAW”。
IN-PACKAGE 包结尾
FLOAT 将任何实数转换为浮点数
TRUNCATE 返回任何实数的整数部分
FLOOR 返回小于等于参数的最大整数 特殊用法:(floor a b) 返回的是a/b的整数值和余数。计算时默认使用返回的整数。
CEILING 返回大于等于参数的最小整数
ROUND 返回最接近参数的整数 > (mapcar #’round ‘(-2.5 -1.5 1.5 2.5))
(-2 -2 2 2);;不做五入,而是取最近的偶数
RANDOM 接受一个整数或浮点数。返回一个小于n的数字
SIGNUM 返回参数的符号。可以返回-1,0或1
FLOAT 转换为浮点数 > (/ 365 12)
365/12;;比值
> (float 365/12)
30.416666
EXPT (expt x n) = x^n
LOG (log x n) = \(\log_{n}x\), 若缺省n,则n默认为e
EXP (exp x) = e^x
SQRT 平方根
SIN、COS、TAN 三角函数
ASIN、ACOS、ATAN 反三角函数
SINH、COSH、TANH 双曲函数
ASINH、ACOSH、ATANH 反双曲函数
PI 常数π
short-float短浮点、single-float单精度浮点、double-float双精度浮点、long-float长浮点
MOST-POSITIVE-FIXNUM最大整数、MOST-NAGATIVE-FIXNUM最小整数 (不同实现下不同)
EVAL 与Python的eval功能相同。可把列表视作代码 > (eval ‘(+ 1 2 3))
6
DEFMACRO 声明宏 (defmacro nil! (x)
(list ‘setf x nil))
也可定义为:
(defmacro nil! (x)
`(setf ,x nil))
> (nil! x)
NIL
> x
NIL
MACROEXPAND-1 展开宏(用于测试) > (macropexpand-1 ‘(nil! x))
(SETF X NIL)
T
, 在反引号表达式中重启求值 > (setf a 1 b 2)
2>
> `(a is ,a and b is ,b)
(A IS 1 AND B IS 2)
,@ 与逗号相似,但将其(本来应该是列表的)参数扒开。 > (setf lst ‘(a b c))
(A B C)
> `(lst is ,lst)
(LST IS (A B C))
> `(its elements are ,@lst)
(ITS ELEMENTS ARE A B C)
GENSYM 自由符号。保证宏定义的变量不会与外面的变量重名。 (defmacro ntimes (n &rest body)
(let ((g (gensym))
(h (gensym)))
`(let ((,h ,n))
(do ((,g 0 (+ ,g 1)))
((>= ,g ,h))
,@body))))
DEFCLASS 声明类 (defclass circle ()
(radius center));;这说明类circle的实例包含两个槽,分别名为radius和center.
MAKE-INSTANCE 创建类的实例 > (setf c (make-instance ‘circle))
SLOT-VALUE 槽的值 > (setf (slot-value c ‘radius) 1)
(槽的属性
:accessor、:writer、:reader 可读写、可写、可读 (defclass circle ()
((radius :accessor circle-radius)
(center :accessor circle-center)))
> (setf c (make-instance ‘circle))
#<CIRCLE #XC5C726>
> (setf (circle-radius c) 1)
1
> (circle-radius c)
1
:initarg 定义参数名
:initform 定义缺省值 (defclass circle ()
((radius :accessor circle-radius
:initarg :radius
:initform 1)
(center :accessor circle-center
:initarg :center
:initform (cons 0 0))))
> (setf c (make-instance ‘circle :radius 3))
#<CIRCLE #XC2DE0E>
> (circle-radius c)
3
> (circle-center c)
(0 . 0)
:acclocation :class 定义类变量 (defclass tabloid ()
((top-story :accessor tabloid-story
:allocation :class)))
> (setf daily-blab (make-instance ‘tabloid)
unsolicited-mail (make-instance ‘tabloid))
#<TABLOID #x302000EFE5BD>
> (setf (tabloid-story daily-blab) ‘adultery-of-senator)
ADULTERY-OF-SENATOR
> (tabloid-story unsolicited-mail)
ADULTERY-OF-SENATOR
)
DEFMETHOD 定义方法。支持重载,甚至可以对单一的对象做特化。 (defmethod combine ((x number) (y number))
(+ x y)
(defmethod combine ((x (eql ‘powder)) (y (eql ‘spark)))
‘boom)
:before :after :around 标准方法组合机制(standard method combination)规定,调用一个函数会调用:around方法,如果有的话;否则,依序调用:before方法、主方法、:after方法
DECLARE、DECLAIM 声明(局部、全局)。
DECLARE(OPTIMIZE (SPEED 3)  (SAFTEY 0)) 编译参数。speed 0~3。3最快。作用在函数里。 (declaim (optimize (speed 3)
(compilation-speed 0)
(safety 0)
(debug 0)));;这块代码让所有代码在任何情况下都尽可能更快。
(DECLAIM(INLINE x)) 使函数x为内联函数。能提高运行速度。递归函数不能内联。 (declaim (inline single?))
(defun single? (lst)
(and (consp lst) (null (cdr lst))))
(DECLAIM (FIXNUM x)) 声明x为定长数(整数)。 (defun poly (a b x)
(declare (fixnum a b x))
(+ (* a (expt x 2)) (* b x)))
(declare (type (vector fixnum 20) v));; 声明了一个仅含有定长数,企鹅长度固定为20的向量。
(常见函数及其破坏性版本
安全 破坏性
append nconc
reverse nreverse
remove delete
remove-if delete-if
remove-duplicates delete-duplicates
subst nsubst
subst-if nsubst-if
union nunion
intersection nintersection
set-difference nset-difference
)
DEFTYPE 定义类型标识符 (deftype multiple-of (n)
`(and integer (satisfies (lambda (x)
(zerop (mod x ,n))))))
> (type 12 ‘(multiple-of 4))
T;;定义了4的倍数的标识符
PACKAGE-NAME 返回包的名字
FIND-PACKAGE 返回一个给定名称的包 > (find-package “COMMON-LISP-USER”)
#<Package “COMMON-LISP-USER” 4CD15E>
SYMBOL-PACKAGE 接受一个符号并返回该符号被 interned 的包
EXPORT 使符号对其他包可视(可用单冒号访问,不可视时只能用双冒号访问)
IMPORT 导入包
USE-PACKAGE 使用包
TRACE 追踪函数,用于调试,可在每次函数调用时显示输入的参数
UNTRACE 取消追踪函数

数字类型

一些神奇算法

  1. 计算1/n的循环节长度算法(返回-1表示没有循环节,返回其他值即为循环节长度):
(defun cycli (n)
  (if (= (gcd n 10) 1)
      (loop with m = 1
            with d integer
            for c upfrom 1
            do (setf (values d m) (floor (* 10 m) n))
            when (= m 1) return c)
      -1))
  1. 给出罗马数字字符串,返回数字的整型值
(defun num (romanChar)
  (case romanChar
   (#\I 1)
   (#\V 5)
   (#\X 10)
   (#\L 50)
   (#\C 100)
   (#\D 500)
   (#\M 1000)))

(defun decoder (roman)
  (setq res 0)
  (dotimes (x (length roman))
    (incf res
    (if (or (zerop x) (<= (num (char roman x)) (num (char roman (1- x))) ))
      (num (char roman x))
      (- (num (char roman x)) (* 2 (num (char roman (1- x))))))))
  res)