我也说说Emacs吧(7) - lisp基础
lisp基础
Lisp是仅次于Fortran的第二古老的着名计算机语言。
Lisp从一开始就与众不同的一点在于,它是基于S-表达式的语言。也就是说,代码和数据是用同一种方式表达出来的。
S-表达式,我们直观上理解,就是用括号括起来的一串列表。
比如:
(+ 1 1)
Lisp会对这个S-表达式进行求值。
S-表达式可以嵌套,比如可以这样写
(+ 1 (* 2 3))
在lisp中,默认的操作是对S-表达式求值。如果是个数字,就对数字直接求值。如果是字符串也是如此。如果是个表,则将第一个原子当成函数名,对其进行求值。
那么,如果我们只想将一个S-表达式当成数据,不要计算怎么办?我们可以使用quote符号来进行指定,比如:
(quote (+ 1 2))
结果就返回(+ 1 2)这个列表。
quote在lisp中实在是太常用了,所以我们可以用符号“’”来作为它的简称。
定义变量
大家都是写代码的老司机啦,我们就直接从定义变量开始说起。
定义变量可以使用set函数。
(set 'three (+ 1 2))
要注意,因为变量名是不求值的,所以要用quote或者'来阻止求值。将来用变量的值的时候就不用quote了。
定义变量的时候,符号是基本上不可能用求值的,所以'是基本上必须的。每次写太麻烦,于是专门有个setq特殊表,直接包含了对于第一个参数的不求值的quote行为。
定义局部变量:let特殊表
let可以定义局部变量。let定义的绑定只在函数内部起作用。
格式:
(let ((变量名 绑定值)(变量名 绑定值)) 语句)
例:
(let ((a 1)(b 2)) (+ a b))
a被赋值1,b被赋值2.最终表达式结果是3.
在let中,如果未指明绑定值,则自动绑定到nil上。
注释
emacs的注释以分号开头,分号之后全是注释。
表处理
car和cdr:取表头和其余部分
下面我们开始进入lisp不同于命令式语言的一个特色功能,表处理。
- car函数:取一个表的第一个元素
- cdr函数:取一个表的除了car取到部分的其它部分
例:
(car '(1 2 3))
将返回1.
(cdr '(1 2 3 4 5))
取得的结果是(2 3 4 5)
nthcdr函数:多次cdr
如果我们要从(1 2 3 4 5)这个表中取(3 4 5)这样的子表,一次cdr不够,需要做两次,像这样:
(cdr (cdr '(1 2 3 4 5)))
有个更简单的写法是使用nthcdr函数:
(nthcdr 2 '(1 2 3 4 5))
nthcdr的第一个参数,如果是0,则直接返回原表。如果是1,则退化成cdr。
cons函数:将car和cdr拼接起来
cons是car和cdr的逆运算。将两个表拼接成一个新表。
例:
(cons '1 '(2 3 4))
将得到(1 2 3 4).
请注意,cons会将第一个参数当成一个元素处理。
比如:
(cons '(1 2 3) '(4 5 6))
得到的结果不是(1 2 3 4 5 6)而是((1 2 3) 4 5 6)
求表长度:length函数
例:
(length '(1 2 4 5))
结果为4.
给表换car和cdr:setcar和setcdr函数
例:
(setq list1 '(1 2 3 4))
(setcar list1 5)
此时再通过C-h v去查list1的值,已经变为(5 2 3 4).
我们再将其后部也换掉:
(setcdr list1 '(6))
list1此时的值已经变成(5 6)
小结
- setq特殊表:定义变量
- let特殊表:定义函数内部的局部变量
- car和cdr,nthcdr:取表头和其余部分
- const: 构造新表
- setcar, setcdr: 给表换头或换其余部分
最后更新:2017-06-13 17:31:40