《ANSI Common Lisp》学习笔记

2.2

(/ (- 7 1) (- 4 2))
从左到右,对每一个参数求值:7求值为7,1求值为1.这两个传给-函数,返回6.(- 4 2)返回2.6跟2传给函数/,返回3.

2.5 函数

用defun来定义函数,一个函数通常有3个以上的参数,第一个是名字,第二个是参数列表,第三个是一个或者多个表达式。一个函数的返回值打算被解释成真或假,则此函数被称为判断式,通常以p结尾.如:(listp 27),判断27是否为列表,返回nil.nil既表示真也用来表示空.

2.6 if/and/or表达式

(if (listp ‘(a b c)) (+ 1 2) (+ 5 6)):判断是否为列表,返回:3
(and t (+ 1 2)):返回最后一个为真的参数:3.
(or t nil):返回最后一个为真的参数:t.

car函数是取出列表的第一个元素,cdr函数是取出列表第一个元素后面所有的元素.写一个函数,判断某个对象是否为列表的元素:

(defun our-member (obj 1st) 
  (if (null 1st) 
      nil
  (if (eql (car 1st)) 
      1st 
      (our-member obj (cdr 1st)))))

实用的方法是先在纸上写出伪代码,如下:

defun our-menber (obj 1st)
  if null 1st
    nill
    if eql (car 1st) obj
       1st
       our-member obj (cdr 1st) 

需要注意的一点是,如果编辑器不能做到匹配括号,想想如何让它做到。否则的话,这个编辑器就别用了。

2.9输入和输出

format函数打印:2 PLUS 3 EQUALS 5。format函数返回值:nil。~A表示会被后面的参数填入,~%表示换行。

 (format t "~A plus ~A equals ~A. ~%" 2 3 (+ 2 3))
2 PLUS 3 EQUALS 5
nil

下面的代码是标准输入

(defun askem (string)
(format t "~A" string)
(read))

> (askem "How old are you?")
How old are you? 29
29

2.10变量

let表达式有两个部分,第一个部分是一系列创造新变量的指令。第二部分是表达式的主题,即调用函数+

> (let ((x 1) (y 2))
(+ x y))
3

下面的代码是判断输入的对象是否为数字,如果是则输出该数字,如果不是,则重新输入。

(defun ask-number ()
  (format t "Please enter a number. ")
  (let ((val (read)))
    (if (numberp val)
      val
      (ask-number))))

定义全域变量/全域常量/判断一个对象是否为全域变量或者全域常量

> (defparameter *glob* 99)
*GLOB*

(defconstant limit (+ *glob* 1))

> (boundp '*glob*)
T

2.11赋值

如果 setf 的第一个参数是一个符号(symbol),且这个符号不是某个局部变量的名字,那么setf 将设置这个符号为全局变量:

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

也就是说,通过赋值,你可以隐式地创建全局变量。 不过,一般来说,还是使用defparameter 显式地创建全局变量比较好。
你不仅可以给变量赋值。传入 setf 的第一个参数,还可以是一个表达式或一个变量名。在这种情况下,第二个参数的值被插入至第一个参数所引用 (refer)的地方:

> (setf (car x) 'n)
N >
x
(N B C)

2.13迭代

打印start到end之间整数的平方。

(defun show-squares (start end)
  (do ((i start (+ i 1)))
    ((> i end) 'done)
   (format t "~A ~A~%" i (* i i))))

下面这个是递归的写法

(defun show-squares (i end)
  (if (> i end)
  'done
    (progn
      (format t "~A ~A~%" i (* i i))
      (show-squares (+ i 1) end))))

还写了一个dolist的迭代函数,没怎么看懂。
## 3.1构建 ##
把两个对象结合成一个有两部分的对象,称之为 Cons 对象,Cons 的一半来指向列表的第一个元素,然后用另一半指向列表其余的元素(可能是别的 Cons 或 nil )。 Lisp 的惯例是使用 car 代表列表的第一个元素,而用 cdr 代表列表的其余的元素。下面的简单代码表示,Cons对象第一个元素是a,第二个元素是nil,第二个元素也可以是列表。

> (setf x (cons 'a nil))
(A)

3.2等式

当我们给 y 赋一个相同的值时, Lisp 复制的是指针,而不是列表。所以无论何时你把一个变量赋给另一个变量时,两个变量会有相同的值(eql)。

> (setf x '(a b c))
(A B C)
> (setf y x)
(A B C)
> (eql x y)
T

如果要复制另外一份列表,需要这么做

> (setf x '(a b c)
y (copy-list x))
(A B C)

3.6存取

找到列表特定位置的元素,我们可以调用nth;而要找到第n个cdr,我们调用nthcdr,需要注意的是,nthcdr返回的是Cons对象,代码如下:

> (nth 0 '(a b c))
A
> (nthcdr 2 '(a b c))
(C)

函数 last 返回列表的最后一个 Cons 对象

> (last '(a b c))
(C)

3.7映射函数,对列表中的每个元素作函数调用

以mapcar跟maplist为例,mapcar是把函数应用至每个列表的元素的结果,直到有的列表没有元素为止maplist是讲列表下一个渐进的cdr传入函数。#’是把函数转换成对象的写法,lambda是定义函数的写法,mapc跟mapcan会在后面讨论。

> (mapcar #'(lambda (x) (+ x 10))
'(1 2 3))
(11 12 13)
> (mapcar #'list
'(a b c)
'(1 2 3 4))
((A 1) (B 2) (C 3))
> (maplist #'(lambda (x) x)
'(a b c))
((A B C) (B C) (C))

对第一个例子稍微的修改,可以实现对两个列表相同索引位置元素的加法。也就是说列表的个数跟你自己定义的函数有关。

> (mapcar #'(lambda (x y) (+ x y))
'(1 2 3)
'(2 3 4))
(3 5 7)

3.8的二叉树跟3.10的集合都没看懂

  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值