原本以为这章很好理解,结果..杯具了。
在lisp中,变量分为两种:词汇变量(lexical),动态变量(dynamic)。#感觉很别扭,估计我翻坏了,虽然与其他语言做了类比,相当于:局部变量和全局变量。可是看了后面,似乎不是这么个回事啊。如果有资深lisper能够给出这两个变量的专业名称(中文),那真是不胜感激了。目前,好吧,就姑且从字面上来称呼这两种变量吧。
作为变量的基本要素之一就是,变量可以持有一个值。而在Lisp中,甚至无所谓值的类型。很爽,但也会有麻烦:只有到了编译的时候才会发现这方面的错误。
最常见的定义变量方式之一:
(defun foo (x y z) (+ x y z))
在定义函数时,不知不觉就定义了3个变量(x,y,z),这样的好处就是:不同的函数调用方互不影响。
另一种定义变量的方式:
(let (variable*)
body-form*)
(let ((x 10) (y 20) z)
...)
为了表现出变量的情况:
(defun foo (x)
(format t "Parameter: ~a~%" x) ; |<------ x is argument
(let ((x 2)) ; |
(format t "Outer LET: ~a~%" x) ; | |<---- x is 2
(let ((x 3)) ; | |
(format t "Inner LET: ~a~%" x)) ; | | |<-- x is 3
(format t "Outer LET: ~a~%" x)) ; | |
(format t "Parameter: ~a~%" x)) ; |
这里有用到LET,他还有一个变种:LET*,简单理解,就是let不允许用前面定义的变量,而let*则可以,例:
(let* ((x 10)
(y (+ x 10)))
(list x y)) ;这是可以的
(let ((x 10)
(y (+ x 10)))
(list x y)) ;这是不行的
(let ((x 10))
(let ((y (+ x 10)))
(list x y))) ;这样也是可以的,与第一种等价
词汇变量及闭包(好别扭的名字)
这里一段比较晦涩的描述,简单代码表示为:
(let ((count 0)) #'(lambda () (setf count (1+ count))))
这里面的count变量只能在随后的匿名函数中使用,过期不候,所以"局部又闭包"啊。
当然,万事有例外,要是函数在关闭时,定义、操作了个全局变量,那么就又不一样了:
(defparameter *fn* (let ((count 0)) #'(lambda () (setf count (1+ count)))))
试试:
(funcall *fn*)
1
(funcall *fn*)
2
(funcall *fn*)
3
动态变量
lisp的动态变量有两种声明方式:
(defvar *count* 0
"Count of widgets made so far.")
(defparameter *gap-tolerance* 0.001
"Tolerance to be allowed in widget gaps.")
两者间的差别是:defparameter必须带变量值,而defvar则无所谓。
虽说全局变量到处都能改,不过规范成一个函数,到处调用还是相当靠谱的:
(defun increment-widget-count () (incf *count*))
还有,虽然全局变量很好用,不过最好还是必须时用,天知道你的代码啥时候变量冲突了捏,一步小心影响了全局可就够喝一壶了。
下面有一段代码,类似于"局部屏蔽全局":
(defvar *x* 10)
(defun foo () (format t "X: ~d~%" *x*))
(foo)
X: 10
NIL
(let ((*x* 20)) (foo))
X: 20
NIL
(foo)
X: 10
NIL
(defun bar ()
(foo)
(let ((*x* 20)) (foo))
(foo))
(bar)
X: 10
X: 20
X: 10
NIL
想要操作全局变量的话:
(defun foo ()
(format t "Before assignment~18tX: ~d~%" *x*)
(setf *x* (+ 1 *x*))
(format t "After assignment~18tX: ~d~%" *x*))
(foo)
Before assignment X: 10
After assignment X: 11
NIL
(bar)
Before assignment X: 11
After assignment X: 12
Before assignment X: 20
After assignment X: 21
Before assignment X: 12
After assignment X: 13
NIL
如果这段代码理解不了,那么停住,理解了再继续。
全局变量的*号是约定成俗的,理论上来说,这样基本上就可以避免局部变量与整体变量间人为失误导致的冲突。
常量
定义方式:
(defconstant name initial-value-form [ documentation-string ])
常量算是一种特殊变量,绑定值后就不再变化。命名约定规则与动态变量相似,用加号(+)包夹。
分配
对于变量而言,赋值是通过宏setf进行的:
(setf place value)
还能一次赋值多个变量:
(setf x 1 y 2)
setf返回值为变量值,所以也可以多变量指同一个值:
(setf x (setf y (random 10)))
Lisp与其他语言赋值对应表:
Assigning to ... Java, C, C++ Perl Python
... variable x = 10; $x = 10; x = 10
... array element a[0] = 10; $a[0] = 10; a[0] = 10
... hash table entry -- $hash{'key'} = 10; hash['key'] = 10
... field in object o.field = 10; $o->{'field'} = 10; o.field = 10
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)
其他的一些修改变量值的方式:
如果需要对变量进行一些针对原值的操作的话,比如:
(setf x (+ x 1))
着实麻烦了些,所以Lisp有内置的一些宏:
(incf x) === (setf x (+ x 1))
(decf x) === (setf x (- x 1))
(incf x 10) === (setf x (+ x 10))
还有ROTATEF和SHIFTF两种常用的宏:
(rotatef a b)
调换a b的值,
(shiftf a b 10)
将值左移:b的值给a,10赋给b。
这一章还有很多晦涩的描述(个人能力有限啊),不过,大体上lisp的变量就是如此了。结尾段给了好多的宏,呵呵,下一章将进入lisp之所以为lisp的世界:宏!
(未完待续)
分享到:
相关推荐
common-lisp-the-language-second-edition.PDF
Practical Common Lisp-1st-2005,官方排版,我为大部分章节加了二级书签
practical common lisp.pdf 实用Common.Lisp编程 英文版
Provides practical advice for the construction of Common Lisp programs. Shows examples of how Common Lisp is best used. Illustrates and compares features of the most popular Common Lisp systems on ...
这本《Practical Common Lisp》之所以号称Practical,正是因为这本书大量介绍Common Lisp在现实世界中的各种应用方式,算是第一本「入世传教」的Common Lisp著作。《Practical Common Lisp》是目前最畅销的Common ...
实用Common.Lisp编程.pdf,2011.10出版
AutoLisp源文件--标注高程.LSP
Common Lisp the Language, 2nd Edition经典,喜欢commonlisp的朋友们的少有资源
ANSI Common Lisp 中文翻译版.pdf 此资源是 ANSI Common Lisp 的中文翻译版,涵盖了 Common Lisp 语言的基础知识和高级主题。该资源包含了 17 章节,从基础的列表、特殊数据结构、控制流程、函数、输入与输出、符号...
计算多个数字之和、计算多条线段长度之和、插入墙高标注、查询多段线顶点坐标并绘制、自动生成页码、绘制示坡线、插入排水箭头 https://blog.csdn.net/qq_24141055/article/details/121446354
cad-lisp-3-表操作.LSP.lsp
Autocad的课件——AutoLISP-Visual-LISP教程.ppt
lisp解密程序-适用于早期的Lisp程序
Common-Lisp.apk
Practical Common Lisp 学习lisp的入门书籍
内含ANSI Common Lisp+On Lisp+实用Common Lisp编程,带书签
common lisp 高清版 lisp语言开发的利器
practical common lisp英文版mobi for kindle https://github.com/akosma/PracticalCommonLisp_ePub
Common-Lisp-Actors, 通用Lisp的actor系统 这是一个简单且易于使用的Actor系统,在。设置需要波尔多螺纹。http://common-lisp.net/project/bordeaux-threads/ 2. 加载 actors.lisp 并开始使用它。 如果你有 Quick
这本《Practical Common Lisp》之所以号称Practical,正是因为这本书大量介绍Common Lisp在现实世界中的各种应用方式,算是第一本「入世传教」的Common Lisp著作。《Practical Common Lisp》是目前最畅销的Common ...