Lisp笔记

Lisp 笔记

common lisp
断断续续更新中…

形式

统一用这种形式来表示,不论是语句还是数据

对于语句,均以函数调用形式进行(少数除外)

形式为(函数名 参数 …)

求值

  • 正确求值
    返回求值结果
  • 求值出错
    报错(进入break loop)

防止求值

(quote 数据)来防止数据被求值

可用‘数据的形式来简略表示

数据类型

  • 整型

    123

  • 字符串
    “abc”
  • 符号
    abc

符号通常不返回自身,故调用时需 引用
- 列表
(a b c)

由于列表和函数调用形式一样,所以使用列表必须引用 ’(a b c)

**空表**和**假**一样 即 ()nil 是完全一样的

列表操作

  • cons

用以将一个元素加入一列表中

> (cons 'a '(b c))
(A B C)

需要注意的是,列表也可以作为元素。故这不是个连接两个列表的操作。

> (cons '(a) '(b c))
((A) B C)
  • car

用以返回列表的第一个元素

> (car '(a b c))
A
  • cdr

用以返回除第一个元素的子表

> (cdr '(a b c))
(B C)
  • first secondthird

分别用以返回列表中的第一、二、三个元素

> (fisrt '(a b c))
A
  • list

用以创建一个列表

> (list 'a 'b 'c)
(A B C)

谓词

即返回真假的函数

  • listp

检测参数是否为列表

> (listp '(a b))
T
> (listp ())
T
> (listp nil)
T
> (listp 'a)
NIL

可见,()nil是一模一样的,都表示假,也都是列表

  • null

空表测试

  • not

逻辑取反

> (null ())
T
> (not nil)
T
> (not ())
T
> (null nil)
T

所以这两个其实是一样的

  • numberp

检测参数是否为数字

> (numberp 'a)
NIL
> (numberp 1)
T

条件与逻辑

  • if

由三个参数组成,参数缺省值为nil。
它与函数不同的地方在于:它并不会对每个参数都求值。
它会根据第一个参数(test表达式)的返回值来选择对第二个(then表达式)还是第三个参数(else表达式)求值。

> (if t
    t
    nil)
T
> (if nil
    t
    nil)
NIL
> (if (listp 'a)
    "是列表"
    "不是列表")
"不是列表"
> (if (listp '(a))
    "是列表"
    "不是列表")
"是列表"
> (if t
    (+ 2 3))
5
> (if nil
    (+ 2 3))
NIL
  • and

求值规则与c语言类似,第一个参数为真才对第二个求值

> (and t (+ 2 3))
5
> (and nil (+ 2 3))
NIL
  • or

也与c语言类似,第一个参数为假才对第二个参数求值

> (or t (+ 2 3))
T
> (or nil (+ 2 3))
5

函数

形式如下

(defun 函数名 (参数表)
    操作)
> (defun my-third (x)
    (car (cdr (cdr x)))
MY-THIRD
> (my-third '(a b c))
C

输入输出

  • format

用于格式化输出

形式如下:

(format 输出位置 "格式字符串和输出内容" 变量)
;t表示输出到缺省位置,通常为顶层
> (format t "hello")
hello
NIL
;~A是变量占位符,~%是换行符
> (format t "~A + ~A = ~A ~%" 2 3 (+ 2 3))
2 + 3 = 5
NIL
  • read

用于读取,缺省状态通常读取顶层

> (read)
a
A

变量

  • let

用以定义局部变量

形式如下:

(let ((变量名 变量值) (变量名 变量值))
    操作)
> (let ((val "php"))
    (format t "~A是世界上最好的语言" val))
php是世界上最好的语言
NIL
  • defparameter

用以定义全局变量,一般全局变量用*包裹,如*glob*

> (defparameter *name* "Nahm")
*NAME*
> *name*
"Nahm"
  • defconstant

用以定义全局常量

> (defconstant age 19)
AGE
> age
19
  • boundp

返回参数是否为全局常量或者变量

注意参数须为符号故需引用

> (boundp '*name*)
T

赋值

  • setf

给全局或局部变量赋值

> (setf *name* "Joe")
"Joe"
> *name*
> "Joe"

如果变量名不存在,则视为隐式定义全局变量。

setf参数为偶数个,故可写成:

> (setf x (list 'a 'b)
    b 2
    c 3)

第奇数个参数还可以为引用,如:

> (setf (car x) 'c)
> C
> x
> (C B)

函数式编程

  • remove

接受一个对象和一个列表,返回一个不含这个值的列表

> (remove 'a '(a b c) )
> (B C)

如果真的想删除,则用返回值重新给原变量赋值即可。

函数式编程是基于返回值而不是函数副作用的编程的方式。

迭代

  • do

第一个参数(变量列表):((变量 初始值 变化操作))

其中变量是符号,初始值和变化操作是表达式。初始状态,变量被赋予初始值,每次迭代被赋予变化操作的值。

第二个参数(列表)会被当作结束条件,即如果这个列表的第一个元素为真则结束。之后的参数会被依序求值。

整个do返回最后一个求值的部分。

例如,一个累加函数:

(defun acc (n)
    (let ((val 0))
        (do ((i 1 (+ i 1)))
            ((> i n) val)
            (setf val (+ val i))
        )
    )
)

故此函数的递归形式为:

(defun acc (n)
    (if (= n 1)
        1
        (+ n (acc (- n 1)))
    )
)
  • progn(工具函数)

接收任意数量表达式,依序求值,返回最后一个的值。

  • dolist

遍历

(defun show-elem (lst)
    (dolist (elem lst)
        (format t "元素:~a~%" elem)
    )
)

函数作为对象

  • function

如果把函数名传给它,它会返回与函数名相关联的函数本身。就像 quote 一样。

如:

> (function +)
#<Compiled-Function + 17BA4E>

#' 是它的缩写,被成为升引号(sharp-quote)

  • apply

我们可以把函数当参数传入函数中,apply就接收函数和实参列表作为参数,并返回执行结果。

如:

> (apply #'+ 1 2 '(3 4 5))
15

注意,apply要求最后一个参数必须为一个列表,但是其之前非函数的实参会与列表有同样的地位

  • funcall

与apply做的事一样,只不过它不需要接收列表参数,直接可对函数后的实参传入所给函数。

如:

> (funcall #'+ 1 2 3)
6

lambda表达式

形如:(lambda (x) (+ x 100))((x) (+ x 100))

lambda字符的作用:

区分函数和列表(common lisp已经不需要显示区分)

由于函数是用列表来表示的,所以为了与普通列表做区分,列表第一个元素是lambda的是函数。

defun宏来创建一个函数并命名,但是函数不需要有名字,并且也不需要用defun来定义,我们可以直接引用函数。

所以我们可以直接引用lambda表达式来调用函数

如:

> ((lambda (x) (+ 1 x)) 1)
2

对lambda表达式做 function 操作获得函数本身

除以上操作外,lambda表达式还能用来写匿名函数

类型

在lisp中变量没有类型,故可以存储各种值。而值是有类型的,有点类似面向对象思想的继承。

比如数字 27 的类型依次是 fixnum、integer、rational、real、number、atom、t。t是所有类型的“基类”。

  • typep

接受一个“对象”和一个类型,判断是否为该类型

如:

> (typep 27 'integer)
T
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值