ansi common lisp 第二章 笔记

1 篇文章 0 订阅

发现仅仅看完一遍,然后做后面的练习题,很不顺。这就做做笔记,每一章小结一下。

2.1、求值规则:

由左至右对实参求值,将它们的数值传入函数,来返回整个表达式的值
以下是当 (/ (- 7 1) (- 4 2)) 表达式被求值时的情形:
1、Lisp 对 (- 7 1) 求值: 7 求值为 7 , 1 求值为 1 ,它们被传给函数 - ,返回 6 。
2、Lisp 对 (- 4 2) 求值: 4 求值为 4 , 2 求值为 2 ,它们被传给函数 - ,返回 2 。
3、数值 6 与 2 被传入函数 / ,返回 3 。
例外:quote操作符,’ 为其缩写
quote 操作符接受一个实参,并完封不动地返回它

> '(+ 3 5)

(+ 3 5)

 

2.2 数据类型:整数(integer)、字符串(string)、符号(symbol)、列表(lists)、特殊值

整数 如256,对自身求值
 >256
256
字符串 双引号包裹起来,如"myString",对自身求值
>“myString”
"myString"
符号英文的单词,如symbol,(通常?)不对自身求值,需quote操作符来引用,值都为大写
>'symbol
SYMBOL
列表 由被括号包住的零个或多个元素,可以嵌套,需要quote操作符引用,否则会被当做函数调用
> '(the list (a b c) has 3 elements)
(THE LIST (A B C) HAS 3 ELEMENTS)
特殊值如nil,t
t,逻辑真:任何非nil都为真
nil,表示空的列表,等同于(),也表示逻辑假
typep:函数 typep 接受一个对象和一个类型,然后判定对象是否为该类型,是的话就返回真:
> (typep 27 'integer)
T

2.3 库函数:list,cons,car,cdr,null,not,listp,numberp,eql,format,read,remove,function,apply,funcall


list:创建列表 (list &rest args)
> (list 'my (+ 2 1) "Sons")
(MY 3 "Sons") 
cons:构造列表,如果传入的第二个实参是列表,则返回由两个实参所构成的新列表(cons se1 se2)
> (cons 'a '(b c d))
(A B C D)
如果第二个实参是空表,则构建一个新表。上面的list,不过就是把几个元素加到 nil 上的快捷方式:
> (cons 'a (cons 'b nil))
(A B)
> (list 'a 'b)
(A B)
car:返回列表的第一个元素(car list)
> (car '(a b c))
A
cdr:返回列表第一个元素之后的所有元素(cdr list)
> (car '(a b c))
(B C)
listp:判断之后的实参是否是列表(listp object)
> (listp '(a b c))
T
> (listp 27)
NIL
numberp:判断之后的参数是否为数字(numberp object)
> (numberp 256)
T
null:如果实参为空列表,则返回逻辑真t(null object)
>(null nil)
t
not: 逻辑取反 (not object)
>(not nil)
t
eql:测试两个实参是否相等,返回逻辑真或逻辑假(eql x y)
>(eql 'a 'b)
nil
format:接受两个或两个以上的实参,第一个实参决定输出要打印到哪里,第二个实参是字符串模版,而剩余的实参,通常是要插入到字符串模版,用打印表示法(printed representation)所表示的对象。
(format destination control-string &rest format-arguments)
> (format t "~A plus ~A equals ~A. ~%" 2 3 (+ 2 3))
2 plus 3 equals 5.
NIL
打印出来的nil为format函数的返回值。 t代表输出到默认的设备,~A由后面的参数填入,~%表示换行
read:标准输入函数。这里简单介绍。没有任何参数时,从默认设备读取。(read &optional (stream *standard-input*) (sb-impl::eof-error-p t) e-of value recursive -p)
> (read)
'a 
'A
read函数的功能很强大。后面章节应该会详细介绍。
remove:接受一个对象和一个列表,返回不含这个对象的新列表(remove item sequence &rest args &key from-end (test #'eql) test-not (start 0) end count key)
> (setf lst '(c a r a t))
(C A R A T)
> (remove 'a lst)
(C R T)
如下所示,remove并没有实际更改lst的内容。这也展示了所谓的函数式编程。
> lst
(C A R A T)

2.4 控制结构 if,do,progn,dolist,


if:通常接受三个实参:一个 test 表达式,一个 then 表达式和一个 else 表达式。若 test 表达式求值为逻辑真 ,则对 then 表达式求值,并返回这个值。若 test 表达式求值 为逻辑假 ,则对 else 表达式求值,并返回这个值:(if test then &optional else)
> (if (listp '(a b c))
(+ 1 2)
(+ 5 6))
3
> (if (listp 27)
(+ 1 2)
(+ 5 6))
11
if 的最后一个实参是选择性的。如果忽略它的话,缺省值是 nil :
> (if (listp 27)
(+ 1 2))
NIL
if是特殊的操作符,因为不会对每一个参数求值,即绕过了一般的求值规则。
do:迭代操作符。 (do varlist endlist &body body)
varlsit形式为(variable initial update) 其中 variable 是一个符号, initial 和 update 是表达式。最初每个变量会被赋予 initial 表达式的值;每一次迭代时,会被赋予 update 表达式的值。
第二个传给 do 的实参可包含一个或多个表达式。第一个表达式用来测试迭代是否结束。接下来在列表中的表达式会依序被求值,直到迭代结束。而最后一个值会被当作 do 的返回值来返回。例子如下:
(defun show-squares (start end)
(do ((i start (+ i 1)))
((> i end) 'done)
(format t "~A ~A~%" i (* i i))))
progn:progn 接受任意数量的表达式,依序求值,并返回最后一个表达式的值。(progn &rest forms)
dolist:遍历列表的元素并处理(dolist (var list &optional result) &body body)
(defun our-length (lst)
(let ((len 0))
(dolist (obj lst)
(setf len (+ len 1)))
len))
function: 特殊操作符,返回函数名字所管理的对象,缩写为#'(function thing)
> (function +)
#<Compiled-Function + 17BA4E>
apply:函数也可以作为实参,apply接受一个函数和实参列表,并返回把传入函数应用在实参列表的结果:(apply function arg &rest arguments)
> (apply #'+ '(1 2 3))
6
funcall:函数 funcall 做的是一样的事情,但不需要把实参包装成列表。(funcall function &rest arguments)
> (funcall #'+ 1 2 3)
6

2.5宏操作符: and,or,lambda


and:逻辑操作符,接受任意数量的实参,如果所有实参都为真,则返回最后一个实参的值(and &rest forms)
>(and t (+ 1 2))
3
如果其中一个参数为假,则其后的参数都不再被求值,返回nil
or:逻辑操作符,接受任意数量的实参,如果有实参都为真,则返回此实参的值,且其后的参数都不再被求值(or &rest forms)
这两个操作符都绕过了一般的求值规则。只有宏操作符和特殊的操作符可以绕过一般的求值规则。
lambda:一个 lambda 表达式是一个列表,列表包含符号 lambda ,接著是形参列表,以及由零个或多个表达式所组成的函数体。(lambda args &body body)
一个 lambda 表达式可以作为函数名。和普通的函数名称一样, lambda 表达式也可以是函数调用的第一个元素,
> ((lambda (x) (+ x 100)) 1)
101

2.6 变量操作 let,defparameter,defconstant,boundp,setf


let:引入新的局部变量。一个 let 表达式有两个部分。第一个部分是一组创建新变量的指令,指令的形式为 (variable expression) 。每一个变量会被赋予相对应表达式的值。一 组变量与数值之后,是一个有表达式的函数体,表达式依序被求值。最后一个表达式的求值结果作为 let 的返回值。(let bindings &body body)
> (let ((x 1) (y 2))
(+ x y))
3
defparameter:定义全局变量,为了避免与局部变量重名,一般全局变量命名为*variable*的形式(defparameter var val &optional doc)
> (defparameter *glob* 99)
*GLOB*
defconstant:定义全局常量(defconstant name value &optional documentation)
>(defconstant limit (+ *glob* 1)) 
LIMIT
若有变量与全局常量重名,会有error发生。
boundp:检查某些符号是否为全局变量或全局常量(boundp symbol)
> (boundp '*glob*)
T
setf:给全局变量或者局部变量赋值
> (setf *glob* 98)
98
> (let ((n 10))
(setf n 2)
n)
2
如果 setf 的第一个实参是符号(symbol),且符号不是某个局部变量的名字,则 setf 把这个符号设为全局变量:
> (setf x (list 'a 'b 'c))
(A B C)
setf的使用非常灵活。传入 setf 的第一个实参,还可以是表达式或变量名。在这种情况下,第二个实参的值被插入至第一个实参所引用的位置:
> (setf (car x) 'n)
N
> x
(N B C)
还可以给 setf 传入(偶数)个实参。如下所示:
(setf a 'b
c 'd
e 'f)

2.7 定义新函数:defun 

通常接受三个以上的实参:一个名字,一组用列表表示的实参,以及一个或多个组成函数体的表达式(defun name args &body body)


> (defun our-third (x)(car (cdr (cdr x))))OUR-THIRD
 
 

                
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值