ANSI Common Lisp 学习笔记(一)
好久不更新Lisp相关内容,因为最近有些琐事,SICP看到第五章,发现很多部分现在都已不太支持,毕竟是个敲代码的,所以就没有记录下来(做兼容和过时的一些内容心理上总有些别扭)。
直接面向实际应用的版本 ANSI Common Lisp,网上搜罗着发现一个不错的中文版文档:https://acl.readthedocs.io/en/latest/zhCN/。
Chapter 2 总结 (Summary)
- Lisp 是一种交互式语言。如果你在顶层输入一个表达式, Lisp 会显示它的值。
- Lisp 程序由表达式组成。表达式可以是原子,或一个由操作符跟着零个或多个实参的列表。前序表示法代表操作符可以有任意数量的实参。
- Common Lisp 函数调用的求值规则: 依序对实参从左至右求值,接着把它们的值传入由操作符表示的函数。 操作符有自己的求值规则,它完封不动地返回实参。
- 除了一般的数据类型, Lisp 还有符号跟列表。由于 Lisp 程序是用列表来表示的,很轻松就能写出能编程的程序。
- 三个基本的列表函数是 ,它创建一个列表; ,它返回列表的第一个元素;以及 ,它返回第一个元素之后的所有东西。
- 在 Common Lisp 里, 表示逻辑 ,而 表示逻辑 。在逻辑的上下文里,任何非 的东西都视为 。基本的条件式是 。 与 是相似的条件式。
- Lisp 主要由函数所组成。可以用 来定义新的函数。
- 自己调用自己的函数是递归的。一个递归函数应该要被想成是过程,而不是机器。
- 括号不是问题,因为程序员通过缩排来阅读与编写 Lisp 程序。
- 基本的 I/O 函数是 ,它包含了一个完整的 Lisp 语法分析器,以及 ,它通过字符串模板来产生输出。
- 你可以用 来创造新的局部变量,用 来创造全局变量。
- 赋值操作符是 。它的第一个实参可以是一个表达式。
- 函数式编程代表避免产生副作用,也是 Lisp 的主导思维。
- 基本的迭代操作符是 。
- 函数是 Lisp 的对象。可以被当成实参传入,并且可以用 lambda 表达式来表示。
- 在 Lisp 里,是数值才有类型,而不是变量。
Chapter 2 习题 (Exercises)
- 描述下列表达式求值之后的结果:
(a) (+ (- 5 1) (+ 3 7))
14
(b) (list 1 (+ 2 3))
(1 5)
(c) (if (listp 1) (+ 1 2) (+ 3 4))
7
(d) (list (and (listp 3) t) (+ 1 2))
(NIL 3)
- 给出 3 种不同表示
'(a b c)
(list 'a 'b 'c)
(cons 'a (cons 'b (cons 'c nil)))
的 。
- 使用
(defun my-fourth (lst)
(car (cdr (cdr (cdr lst)))))
与 来定义一个函数,返回一个列表的第四个元素。
- 定义一个函数,接受两个实参,返回两者当中较大的那个。
1 (defun bigger-number (a b) 2 (if (and (numberp a) (numberp b)) 3 (if (> a b) 4 a 5 b)))
- 这些函数做了什么?
(a) (defun enigma (x)
(and (not (null x))
(or (null (car x))
(enigma (cdr x)))))
检查列表x中是存在nil
(b) (defun mystery (x y)
(if (null y)
nil
(if (eql (car y) x)
0
(let ((z (mystery x (cdr y))))
(and z (+ z 1))))))
统计列表y中对象x的第一次出现的位置
- 下列表达式, 该是什么,才会得到相同的结果?
(a) > (car (x (cdr '(a (b c) d))))
B
car
(b) > (x 13 (/ 1 0))
13
or
(c) > (x #'list 1 nil)
(1)
apply
- 只使用本章所介绍的操作符,定义一个函数,它接受一个列表作为实参,如果有一个元素是列表时,就返回真。
(defun has-list (lst) (if (not (null lst)) (if (listp (car lst)) t (has-list (cdr lst)))))
- 给出函数的迭代与递归版本:
- 接受一个正整数,并打印出数字数量的点。
- 接受一个列表,并返回 在列表里所出现的次数。
- 一位朋友想写一个函数,返回列表里所有非 元素的和。他写了此函数的两个版本,但两个都不能工作。请解释每一个的错误在哪里,并给出正确的版本。
(a) (defun summit (lst)
(remove nil lst)
(apply #'+ lst))
remove生成不包含nil的列表并不对原有列表进行修改,最后的加和是对源列表进行的操作,并没有剔除nil
(defun summit (lst) (apply #'+ (remove nil lst)))
(b) (defun summit (lst)
(let ((x (car lst)))
(if (null x)
(summit (cdr lst))
(+ x (summit (cdr lst))))))
递归没有跳出部分,需要添加lst非空判断来结束递归
(defun summit (lst) (if (null list) 0 (let ((x (car lst))) (if (null x) (summit (cdr lst)) (+ x (summit (cdr lst)))))))
新手一枚,如有不足还望指出。
总结和习题来自:https://acl.readthedocs.io/en/latest/zhCN/。如需清除,请联系邮箱:1144054302@qq.com或回复。