1 简介

Common Lisp (lisp - 列表处理) Common Lisp 官网

1.1 符号运算

lisp 中, 每个符号都会存储为一个对象 object . 加号代表了一个内置的函数,后面的是参数,这种标记方式叫做 逆波兰标记法

(+ 2 2) ; this is an operation

关于符号的四个重要点:

  1. lisp 对要处理的对象不附带任何附加意义
  2. append, length, 和 + 号一样都是 lisp 内置的函数
  3. 符号不区分大小写
  4. 符号的范围很广,标点也可以用来命名符号
(append '(Pat Kim) (list '(John Q Public) 'Sandy))
(length (append '(Pat Kim) (list '(John Q Public) 'Sandy)))

1.2 变量

通过符号进行定义变量

(setf p '(John Q Public))
(setf x 10)

变量和函数名称可以一样,因为作为变量 length 没有值

(print (length '(wu dan yang)))
(setf length 10)
(print length)

1.3 特殊形式

特殊形式即 special form , setf 是个特殊形式(只对第二个参数进行求值, 违背了函数的定义)

  1. defun
  2. defparameter
  3. setf
  4. let
  5. case
  6. if
  7. function(#')
  8. quote(')

1.4 列表

lisp 中, 最多的就是一对一对的括号, 这些在最初都是用来表示为列表的, 不过 lisp 将其中一些列表赋予了不同的意义. 变量前面使用会有一个 ' , 不指定就是会解析成函数调用. 访问列表

(setf x '((1st element) 2 (element 3) ((4)) 5))
(length x)
(first x)
(second (first x))
(list x)

构建列表

(setf p '(john p public))
(cons p '2)
(first (last p))
(last p)

1.5 定义函数

特殊形式 defun 来定义函数

(defun function-name(parameter)
   "document string"
   function-body)
(defun last-name(name)
   "select last name"
   (first (last name)))
(setf p '(john p public))
(last-name p)

1.6 使用函数

(mapcar #'last-name names)

#' 标记代表后面的标识符是个函数 mapcar 会对 names 中的每个元素应用 last-name 并且返回一个 list 相当于:

(list (last-name (first names))
      (last-name (second names)))
      ...

mapcar 会将每个列表的第一个元素应用函数, 直到一个列表的元素个数不够了

(mapcar #'+ '(1 2 3 4) '(1 2 3 4) '(1 2 3 4) )

常量: 常用 title 星号来表示

(defparameter *titles*
   '(Mr Mrs Miss Ms Sir Madam Dr Admiral Major General)
   "A list of titles that can appear at the start of a name.")

trace 用于跟踪函数的执行过程 untrace 取消跟踪

1.7 高阶函数

一个函数将其他的函数作为参数, 这种函数叫高阶函数. apply 对列表中的每个数据进行操作

(defun mappend(fn the-list)
        "Apply fn to each element of list"
        (apply #'append (mapcar fn the-list)))
        (setf test-list '((1 2) (10 20) (300 600)))
        (apply #'append test-list)

递归的 mappend 这里使用了 funcall, funcall 与 apply 类似, 但是 funcall 的参数是单独的, apply 是个列表

(defun mappend (fn the-list)
        "apply fn to each element of list and append  the results"
        (if (null the-list)
            nil
            (append (funcall fn (first the-list))
                    (mappend fn (rest the-list)))))
(funcall #'+ 2 3)

1.7.1 匿名函数 lambda

(lambda (parameters…) (body…))

使用 lambda 函数, 必须使用 #' 符号, 使用 #' 标记可以获得一个函数本身而不是其名称

((lambda (x) (+ x 2)) 4)
(funcall #'(lambda (x) (+ x 2)) 4)

书中1(lambda (x) (+ x 2)) 这种形式会报错 Error:LAMBDA is not a function, 但是我用 clozure lisp (common lisp 的一种) 试了一下, 出现的是这个:

#<Anonymous Function #x3020008E2AAF>

匿名函数这个特性也存在于 python / php 等语言中.

因为以下两点, 匿名函数很有用:

  1. 不污染变量
  2. 匿名函数的存在可以使程序在运行时进行创建函数, 这些 运行时函数 也叫做 闭包

1.8 其他数据类型

lisp 中含有 25 种不同类型的对象. 不同类型的对象有着不同的作用, 就像 string 主要用来打印信息, symbols 主要用来与其他对象建立联系.

string 这种类型的表示方法为两个双引号包起来 -> "a string"

1.9 lisp 运行规则

  1. 每个表达式都是一个列表或者一个原子.
  2. 每个列表要么被解析成 special form , 要么是 function .

未完待续…

Last Updated 2017-04-17 一 11:04.
Render by hexo-renderer-org with Emacs 25.3.1 (Org mode 9.1.1)