lisp-基本概念
执行环境(command)(command)(command)Lisp中,涉及到操作相关,都必须是一个列表,也就是,必须使用小括号()进行包裹。大部分的交互式界面推出方式如下enviormentcommandshellexitpythonexit()lisp(exit)所以,对于这个环境的理解可能更明确了一些。一般顺序(funcdat...
执行环境
( c o m m a n d ) (command) (command)
Lisp中,涉及到操作相关,都必须是一个列表,也就是,必须使用小括号()
进行包裹。
大部分的交互式界面推出方式如下
enviorment command shell exit python exit() lisp (exit) 所以,对于这个环境的理解可能更明确了一些。
一般顺序
( f u n c d a t a _ 1 d a t a _ 2 … ) (func \quad data\_1 \quad data\_2 \quad \dots ) (funcdata_1data_2…)
默认的执行顺序,是对于每一个元素进行求值,然后统一进行运算;可以看作是reduce
的操作。
可以尝试一下如下操作
(+ 1 2)
(+ 1 2 3)
(exit)
(exit 0)
(list 1 2 3 4 5)
基本数据
数值类型
数值类型是最直接的类型,不用经过计算或者转换
2
3
4
字符类型
如果输入了其他字符,一般是不被接受的,因此需要告诉lisp不需要去计算,保留原样即可。
(quote a)
布尔类型
character | value |
---|---|
T | true |
NIL | false |
和数值一样,字面量可用。
列表
列表的话,算是最常用的类型了。
我们所需要的环境,也可以算作是一个列表。
一般使用list进行列表的定义
(lisp a b c d)
一些操作
不操作
(quote a)
quote
的操作就是不操作,原样保留。但是特殊的是,它是单值操作,也就是操作元素只允许一个数据。
(list (quote (+ 1 2)) (+ 1 2))
可以好好体会一下
'q
如果是全称,也就是quote
,需要环境()
,但是,如果使用的是'
,直接就可以进行操作了。
列表
(list a b c)
把三个数据组成列表,但是还有一种直接定义的方式
(quote (a b c))
因为不进行计算的直接保留,所以还是原始的列表形式。
`(a b c)
列表操作
转化成列表是一种操作,同时,列表也是一种元素,可以被操作。
- 获取第一个元素
(car '(a b c)); A
- 获取第一个之后的元素
(cdr '(a b c)); (B C)
可以看到
- 字符会被显示为大写
car
获取的是单个元素,cdr
返回的是包含剩余元素的列表(car (cdr (cdr '(a b c d e f))))
通过这种方式,我们可以进行任意元素的获取
赋值
(let ((a 1)) (format t "first ~A~%" a) (format t "second ~A~%" a))
- 关键字:let
- 元组赋值:赋值操作在
()
中,但是每一对赋值表示为元组 - 影响范围:顺序执行赋值之后的操作语句
判断
(if T 2 3); 2
if
是一个三元素的操作,通过条件筛选元素。
(if (> 2 1) (+ 2 3) (- 10 3)); 5
逻辑
- and
(and T NIL); NIL
- or
(or T NIL); T
- not
(not nil);T
(null nil);T
相等
(eql 'a 'a);T
(eql 1 1); T
(eql '(a b c) '(a b c)); NIL
只能进行数值/字面量比较
函数
(defun add (a b) (+ a b))
(add 1 4); 5
其中包含四个部分
- 关键字:defun
- 函数名:add
- 参数表:(a b)
- 函数体:(+ a b)
后续的操作都算作是函数体
- 单操作函数体
(defun _max (a b) (if (> a b) a b)) (_max 4 6); 6
- 多操作函数体
(defun add (a b) (format t "before~%") (format t "~A + ~A = ~A~%" a b (+ a b)) (format t "after~%") )
递归
检查一个元素,是否存在于一个列表中
(defun contains (obj lst) (
if (null lst) nil (
if (eql obj (car lst)) T (contains obj (cdr lst))
)
))
输出
(format t "~A + ~A = ~A~%" 1 2 (+ 1 2)); 1 + 2 = 3
- 关键字:format
- 操作符:t
- 占位符:
~A
- 换行符:
~%
输入
(read)
一直阻塞等待输入。
参数输入
(defun hello () (format t "hello, wath's your name?~%") (let ((name (read))) (format t "斯巴拉西, we are both named ~A~%" name) ) )
定义赋值
一般赋值
前面的
let
可以进行赋值,但是值得注意的是,它引入的是局部变量。(let ((p 1)));赋值 p;此时显示是报错的,因为外部访问不了局部变量
对于全局变量的定义和赋值,一般使用setf
(setf m 888);
m;外部是可以直接进行访问的
全局变量
(defparameter judas 99)
- 全局变量重新定义,会覆盖原来的值
setf
进行赋值,会更新原来的值
全局常量
(defconstant fuck 99)
- 全局常量的重新定义,名字冲突会报错
- 全局常量的复制操作,会报错
迭代
(defun godme (start end) (
do ((i start (+ i 1)))
((> i end) `done)
(format t "value : ~A~%" i)
))
-
关键字:do
-
初始化和更新:
((i start (+ i 1)))
,其中传入的单个数据是一个三元组- 变量声明:
i
- 初始化:
start
- 更新操作:
(+ i 1)
- 变量声明:
-
结束条件:((> i end) `done),满足条件就会退出
-
函数区域:剩下的可以跟随多个操作语句
(defun godme (start end) (
do ((i start (+ i 1) ) (j end (- j 1)))
((eql i j) `done)
(format t "i=~A j=~A" i j)
(format t " -end~%")
))
函数对象
函数对象
很多字符,都不能单纯的作为字面量进行使用,需要进行语义保留
quote
,除非是已经定义的变量。那么,操作符号是什么。
经过测试,操作符号是可以进行quote
的,也就是说,直接输入的时候,他们还代表着其他的含义。
单纯的输入
+
,会打印上一条命令
他们都是函数,每次都是直接进行的调用,他们的实体可以使用function
进行查看。
(function +);#<SYSTEM-FUNCTION +>
(function eql);#<SYSTEM-FUNCTION EQL>
遗憾的是,下面这条命令是失败的
(function function)
同quote
,function
也有简写模式#'
#' eql
#' +
函数参数
apply
(apply #'+ '(1 2 3))
(apply #'+ 1 2 '(3))
- 支持函数作为参数
- 后续跟随多个参数
- 最后一个参数必须是列表
用python
表示一下的话,就是这样了
def apply(func, *args):
return func(*args)
funcall
(funcall #'+ 1 2 3)
和apply
相同,比较好的是,最后一个参数不强制要求为列表。
匿名函数
使用lambda
而非defun
,可以省略函数名。
((lambda (x) (+ x 99)) 1);100
实体和调用
(setf add (lambda (x y) (+ x y)))
(funcall add 1 2)
创建了一个函数的变量add
,相较于其他变量,它的特殊点在于可以操作其他变量。
异同
(add 1 2);异常
有必要注意一下,此时获取的这个函数变量,我们居然无法直接进行调用。
更多推荐
所有评论(0)