Ansi Common lisp 读书笔记 0

第一、二章

简单认识一下lisp#

根据 SICP 课程的提出的,认识一门语言需要问的三个问题

  • 它的最基本单元是什么
  • 它是怎么组合这些单元的
  • 它抽象这些组合方法是什么 这本书我们都带着这些问题去看

表示方法#

首先,lisp 和传统的编程语言有一点很不一样。它模糊了数据和方法,统一使用 “s 表达式” 来表示。 例如函数,不再是声明一个名字和参数列表,之后实现它这种结构,而是像写一个表达式

(defun sum (n)
  (let ((s 0))
    (dotimes (i n s)
      (incf s i))))

类似的,它的数据也是如此表示

'(1 2 3)

“'” 单引号的作用是一个语法糖,方便的表示后面的是数据,不是需要求值的表达式

lisp 还有一个符号的概念,这里没有介绍太清楚。只是先了解有这个东西,还有他也可以是被求值的,但是一般用的时候不需要求值,所以引用的时候也使用单引号来引用

'Symbol

结构#

lisp 是一个循环自解释的系统 它会把自己语言的高级抽象,通过自己的语言来展开,之后求值。如果要求值的表达式还是比较高级的抽象,会又重新进行展开,之后再求值。这样一直循环到可以用最基础的实现来求值,得出最后结果的过程

列表操作符#

  • cons 链接 list 的第一个元素和后面的部分
  • car 取 list 的第一个元素
  • cdr 取 list 除了第一个元素后面的部分

谓词#

一般的,在 lisp 做条件判断的错作符称作谓词,一般为了可读性,自定义的谓词使用“p”结尾,例如

(listp '(a b c))

这个表达式求是判断(a b c)是否是list。值的结果是真,用 “t” 表示 上面的结果会返回

T

关于 not 和 null#

这里书里只介绍做相同的事,但是没有具体的解释。我们以后在看

函数#

函数的定义,我们使用 defun 操作符

关于递归#

这里只是说了lisp可以做递归,并举了些例子,并没有近一步说明。

先简单说一下,基本的递归是每次的执行的环境保存在栈中,之后到最内层的时候逐步的回归出栈。 递归在 lisp 的编译器中,会整体判断一个操作前后是否对某个值做入栈操作,来做尾递归的优化。

打印函数#

common lisp 使用format函数打印

占位符是 ~A,对应最后面参数列表的每个参数 ~% 表示换行

读入函数#

书中说 read 是一个解释器。

解释器#

解释器是对应的是求值器,他俩组合就是是前面说的循环求值的过程,lisp 的本质。 书里这里没有更多的解释,以后再看。

变量#

变量分为局部变量和全局变量

在sicp中,会叫做自由变量和限制变量 这个说法个人觉得一开始比较难理解,但是是说到本质的。 自由变量是可以替换的,替换前后程序的意义没有变换。限制变量是不可以的,如果换了,程序的意义就变了 如:

(setq c 1)
(setq d 2)
(defun f (x y)
  (+ x y c))

如果将所有的x替换成m,y替换成n,意义完全没有变换 而要是把c换成d,程序的意义就变了

赋值#

对于复制,在函数试编程里,复制是破坏无状态的开始,让事情变得更的复杂。但是复制也解决一些问题必要的工具。 在其他 lisp 实现中(scheme)有复值的操作会以感叹号结尾来提示此操作会引入状态改变。

common lisp 中使用setf 操作符来负值

迭代#

在计算机更接近机器语言的层面,循环是跳转。在其他语言中是迭代的关键字来表示,lisp中是用递归,只是表现形式的不同 common lisp 中有定义的宏来实现迭代

函数作为对象#

其他对象的引用使用quote “'",函数的引用使用sharp-quote “#'"。

引用#

前面提到过两次引用了,本质都是防止引用的对象被求值

apply#

apply 书中是说了它的作用是把函数何其参数传给它,等价于执行函数及参数

funcall#

类似于 apply,都是接受函数引用和不定个数的参数,效果也相同,只是最后一个参数funcall 可以不是 list,apply 最后一个参数必须是 list

lambda#

在 lisp 中,一切皆可 lambda,例如 lambda 可以是赋值

((lambda (x y)
  do some thing
  ) 1 2)

相当于

(let ((x 1)
      (y 2))
      do some thing
      )

他们的效果是一样的

类型#

在 lisp 中,变量没有类型,但是为了使用类型,可以显示的标注一个变量的类型,说中说后面会讨论。在 sicp 中,解决一个横向隔离问题时引入了“类型”,只是用cons 将一个符号和变量cons起来,在去这个变量的时候使用cdr,取变量类型的时候使用car

书中说lisp中数值才有类型,详细的在后面会讨论