Gre*_*ans 4 lisp scope sbcl common-lisp
使用emacs或我的Android应用程序时,我运行
(defun big (num) (setf num2 5)(little num)))
(defun little (num)(+ num2 num))
Run Code Online (Sandbox Code Playgroud)
Little 愉快地接受num2但是当我在我的SBCL repl(使用sublimetext3)中运行它时它没有.
它是否正确?
没有为num2创建全局变量的解决方法是什么?
我可以传递第二个论点 (little num num2)
但是当我试图little 在列表上映射时,这不会起作用.因为mapcaring正确时我只能有一个参数?
cor*_*ump 10
请阅读§6.来自Practical Common Lisp的变量.
与Emacs Lisp不同,Common Lisp默认依赖于词法范围(Emacs Lisp 默认是动态的).动态范围(即无限范围和动态范围)是通过声明特殊变量来提供的,按照惯例,它们用星号围绕它们的名称(名为"耳罩")编写,如*standard-output*.您使用defparameter或defvar声明这些变量.由于它具有全局效果,因此不应该从内部函数中使用它们; 同样,您的使用setf未在Common Lisp中定义:num2之前未在范围内声明名称的变量; 此外,即使它确实如此,对局部变量使用全局/特殊变量也是不好的风格.
使用特殊变量,您可以在本地重新绑定标准输出:只有当代码位于let绑定体内时,新值才可见:
(let ((*standard-output* *error-output*))
(print "Stream redirection"))
Run Code Online (Sandbox Code Playgroud)
默认情况下,print写入绑定到的流*standard-output*; 这里,流本地绑定到给定的流*error-output*.一旦你逃脱let,*standard-output*恢复到它以前的值(想象有一个堆栈).
使用词法范围,您的代码只能访问在代码周围的文本(以及全局范围)中可见的绑定,并且范围是无限的:即使在代码返回后,也可以访问绑定(有时是间接的)的let:
(let ((closure
(let ((count 0))
(lambda () (print (incf count))))))
(funcall closure)
(funcall closure))
;; prints:
;; 1
;; 2
Run Code Online (Sandbox Code Playgroud)
该lambda表达式创建一个闭包,它捕获名为的变量count.每次调用它时,它都会增加count变量并打印出来.如果再次计算相同的代码,则定义另一个闭包并创建另一个具有相同名称的变量.
因为mapcaring正确时我只能有一个参数?
不完全是; 通过调用的函数mapcar应该能够尽可能多元素的数量至少接受列表被赋予它(和它应该也不会要求更具强制性参数):
(mapcar (lambda (x y) (* x y))
'(1 2 3)
'(0 3 6))
=> (0 6 18)
(mapcar #'list '(1 2) '(a b) '(+ /))
=> ((1 a +) (2 b /))
Run Code Online (Sandbox Code Playgroud)
该函数也可以是闭包,并且可以使用特殊变量.
(defun adder (x)
(lambda (y) (+ x y)))
(mapcar (adder 10) '(0 1 2))
=> (10 11 12)
Run Code Online (Sandbox Code Playgroud)
该adder功能需要一个数x,并返回它接受若干封闭y并返回(+ x y).
如果您更喜欢动态范围,请使用耳罩并为其指定一个有意义的名称:
(defparameter *default-offset* 0)
Run Code Online (Sandbox Code Playgroud)
......并定义:
(defun offset (x)
(+ x *default-offset*))
Run Code Online (Sandbox Code Playgroud)
你也可以mapcar:
(let ((*default-offset* 20))
(mapcar #'offset '(1 2 3)))
=> (21 22 23)
Run Code Online (Sandbox Code Playgroud)
正如jkiiski在评论中所说,你也可以(declare (special ...))在通常放置声明的位置(当输入a let,a defun,...时)声明特殊变量 .您也可以使用特殊运算符progv.这对于具有"不可见"变量非常有用,这些变量仅由一组函数知道以交换信息.你很少需要它们.
| 归档时间: |
|
| 查看次数: |
188 次 |
| 最近记录: |