Lisp笔记

1 篇文章 0 订阅
1 篇文章 0 订阅

变量

动态变量

defvar defparameter

(dafvar *paraname* default-value
"Documentation"

defparameter始终赋值
defvar只初始化,且可以不赋值

动态变量和词法变量的不同

使用let形式操作动态变量会产生和词法变量不一样的效果
词法变量在声明函数时确定了作用域。即说的时候是几就是几,被调用时还是声明时那个作用域的值。
动态变量在调用函数时寻找调用语境的作用域。即用的时候看环境,包含动态变量的函数调用的作用域的值决定函数内这个变量的值。

(let ((y 2))
 (flet ((foo () y))
  (let ((y 3))
   (print (foo))) ;foo函数内的y取声明foo时的值
  (print (foo))))
------------------
2
2
(defvar *y* 1)
 (let ((*y* 2))
  (flet ((foo () *y*));*y*与声明时环境无关,取调用时所处环境的值
   (let ((*y* 3))
    (print (foo)))
   (print (foo))))
------------------
3
2

本质是foo函数中动态变量/特殊变量是像当前作用域寻找*y*这个值,而词法变量是向声明函数时y的作用域寻找该值。
窃以为如果foo是个宏,词法变量和动态变量会获得一样的效果。回头学了宏来试一试。

脑内解释

词法变量:因为值跟上下文的文本关系更强,与调用的环境无关。
动态变量:同样的函数在不同作用域下可能变现出不同值,叫动态变量合情合理。不适合称为全局变量。

常量

defconstant
+variablename+常量命名,不能被用于形参和重绑定

赋值

setf place value
setf place1 value1 place2 value2
返回最后赋予的值
(setf x (set y 10)) = 把复制给y的结果赋给x
Simple variable: (setf x 10)
Array: (setf (aref a 0) 10)
Hash table:(setf (gethash 'key hash) 10)
Slot named ‘field’: (setf (field o) 10)

修改宏

(incf x) = (setf x (+ x 1))
(incf x 10) = (setf x (+ x 10)
修改宏一般可以保证从左到右执行,保证参数和位置形式的子形式只被执行一次。

shiftf rotatef

(shiftf a b c)值向左传递,返回最左
(rotatef a b c)值向左传递,最右变量获得最左的值,返回nil

展开期(macro expansion time)
运行期(runtime)

(defmacro name (parameter*)
  "Optional documentation string."
  body-form*)

do

(do (variable-definition*)
(end-test-form result-form*)
statement*)

variable-definition

(var init-form step-form)

数字、字符、字符串、符号引用

#\a字符a
#\Space空格
'bar ->BAR单引号加字符串,如’bar,表示这个字符串的符号(symbol)对象。

集合

向量

#(a b c)#号打头的列表

集合操作

find
count
subsitute
position
remove
关键字
:test 类似于上述函数的-if版本,如count-if。
(count #\a #(a b c d e)) >1
(count #\a #(1 2 3 4 5) :test $'evenp) > 2
(count-if #'evenp #(1 2 3 4 5)) > 2
:key 对集合元素做一定提取,比如元素也是合集,可以用它提取选择提取哪个。
(count #\a #((a 10) (b 20) (c 30)) :key #'first)其中处理(a 10)时,就会提取第一个元素a和#\a进行对比。
:start
:end Num|Nil若指定Nil,则到末尾
:from-end T从后往前
:count在remove和substitute中,表示生效几次

合并

concatenate

(concatenate 'vector #(1 2 3) '(4 5 6)) -> #(1 2 3 4 5 6)
(concatenate 'list #(1 2 3) '(4 5 6)) -> (1 2 3 4 5 6)
(concatenate 'string "abc" '(#\d #\e #\f)) -> "abcdef"

merge (含排序)

(merge 'vector #(1 3 5) #(2 4 6) #'<) -> #(1 2 3 4 5 6)
(merge 'list #(1 3 5) #(2 4 6) #'<) -> (1 2 3 4 5 6)

排序

sortsort-stable
破坏性:改变参数

(setf my-sequence (sort my-sequence #'string<));如果不破坏得这样写
;rather than just this:
(sort my-sequence #'string<)

:key 关键字,提取的关键字只用于排序算法,而不是排序内容

子序列

(defparameter *x* (copy-seq "foobarbaz"))
(setf (subseq *x* 3 6) "xxx") ; subsequence and new value are same length
*x* -> "fooxxxbaz"
(setf (subseq *x* 3 6) "abcd") ; new value too long, extra character ignored.
*x* -> "fooabcbaz"
(setf (subseq *x* 3 6) "xx") ; new value too short, only two characters changed
*x* -> "fooxxcbaz"

mismatch

(mismatch "foobarbaz" "foom") -> 3
;It returns NIL if the strings match. MISMATCH also takes many of the standard keywordarguments: 
; a :key argument for specifying a function to use to extract the values to be compared;
; a :test argument to specify the comparison function; 
; :start1, :end1, :start2,and :end2 arguments to specify subsequences within the two sequences. 
; :from-end argument of T specifies the sequences should be searched in reverse order, causing MISMATCH to return the index, in the first sequence, where whatever common suffix the two sequences share begins.
(mismatch "foobar" "bar" :from-end t) -> 3;这个3仍然左起第3个

序列谓词

(every #'evenp #(1 2 3 4 5)) -> NIL
(some #'evenp #(1 2 3 4 5)) -> T
(notany #'evenp #(1 2 3 4 5)) -> NIL
(notevery #'evenp #(1 2 3 4 5)) -> T
;These calls compare elements of two sequences pairwise:
(every #'> #(1 2 3 4) #(5 4 3 2)) -> NIL
(some #'> #(1 2 3 4) #(5 4 3 2)) -> T
(notany #'> #(1 2 3 4) #(5 4 3 2)) -> NIL
(notevery #'> #(1 2 3 4) #(5 4 3 2)) -> T

映射

map
跟mathamatica的map一样的用法,给定一个谓词把n个序列的元素进行运算,返回一个新序列
*需要指定类型 'list or 'vecotr

(map 'vector #'* #(1 2 3 4 5) #(10 9 8 7 6)) -> #(10 18 24 28 30)

map-into
把返回结果放进第一个参数里(一个序列)
如果长度不统一以最短的为准

(map-into a #'+ a b c)

reduce
:initial-value 逻辑上提供一个第一位

(reduce #'+ #(1 2 3 4 5 6 7 8 9 10)) -> 55

哈希表

make-hash-table创建哈希表
hash的等价判断可以通过:test关键字传递,但仅接受EQUAL EQEQUALP

(defparameter *h* (make-hash-table))
(gethash 'foo *h*) -> NIL
(setf (gethash 'foo *h*) 'quux)
(gethash 'foo *h*) -> QUUX

GETHASH隐式地返回两个值,“值”和“是否存在”。与形参形式中(c Nil c-p)/(形参名 默认值 是否赋值)很像,用于判断是传值为Nil还是因为没有值才Nil
*多重返回值的工作方式决定,如果没有显示处理,额外返回值会被丢弃。即视为一个返回值。

(defun show-value (key hash-table)
  (multiple-value-bind (value present) (gethash key hash-table)
    (if present
      (format nil "Value ~a actually present." value)
      (format nil "Value ~a because key not found." value))))
(setf (gethash 'bar *h*) nil) ; provide an explicit value of NIL
(show-value 'foo *h*) -> "Value QUUX actually present."
(show-value 'bar *h*) -> "Value NIL actually present."
(show-value 'baz *h*) -> "Value NIL because key not found."
迭代

maphash两个参数

(maphash #'(lambda (k v) (format t "~a => ~a~%" k v)) *h*)

remhash 按key删除一个表格内容

(maphash #'(lambda (k v) (when (< v 10) (remhash k *h*))) *h*)

点对单元

(CAR . CDR)

(cons 1 2) -> (1 . 2)
(car (cons 1 2)) -> 1
(cdr (cons 1 2)) -> 2
;Both CAR and CDR are also SETFable places—given an existing cons cell, it’s possible toassign a new value to either of its values.3
(defparameter *cons* (cons 1 2))
*cons* -> (1 . 2)
(setf (car *cons*) 10) -> 10
*cons* -> (10 . 2)
(setf (cdr *cons*) 20) -> 20
*cons* -> (10 . 20)

列表就是点对单元单链表

(cons 1 nil) -> (1)
(cons 1 (cons 2 nil)) -> (1 2)
(cons 1 (cons 2 (cons 3 nil))) -> (1 2 3)

列表

多数列表函数使用函数式编写,这么做是有好处的,因为他们可以在返回结果中直接使用一部分实参。
比如append这样的函数用于链接2个列表,基于点对单元特征,可以把任意新列表的CDR连接到后者。

破坏性

基于上文提到的修改点对单元的操作,可能产生破坏参数的特征。只有当确认参数不在使用时,调用破坏性函数才是安全的。

(defparameter *list-1* (list 1 2))
(defparameter *list-2* (list 3 4))
(defparameter *list-3* (append *list-1* *list-2*))
;After evaluating these forms, you have three lists, but *list-3* and *list-2* share structure just like the lists in the previous diagram.
*list-1* -> (1 2)
*list-2* -> (3 4)
*list-3* -> (1 2 3 4)
;Now consider what happens when you modify *list-2*.
(setf (first *list-2*) 0) -> 0
*list-2* -> (0 4) ; as expected
*list-3* -> (1 2 0 4) ; maybe not what you wanted

破坏性 & 回收性

回收性函数
NREVERSENon-consing,不分配新的点对单元。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值