LISP本地/全局变量分配 [英] LISP local/global variable assignment

查看:310
本文介绍了LISP本地/全局变量分配的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

如果我们定义一个类似

的函数

(defun foo(x)
  (setf x somevalue))

x是定义为局部变量还是全局变量?使用setf/q将值设置为全局值. 如果是全局的,谁能告诉我如何在let以外的Lisp中定义局部变量?

谢谢!

考虑以下示例

(let ((x 0)) 
  (defun foo (y) 
    (when (equal x 0) (setq x y)) 
    (when (< x y) (setq x y))
    x))

当我像(foo 2)一样向foo提供一些输入时,它返回2,如果我们再次使用(foo 1)执行该函数,它仍然返回2,而(foo 3)返回3.这就是我真正想要的但是问题是怎么可能的,因为如果我尝试从clisp终端访问函数外部的变量x,我将无法执行.如果再次访问该函数,它似乎保留了前一个x的值.

谢谢!

解决方案

要绘制与C,C ++,Java或Python等其他语言的相似之处,即使代码不是这样,您的代码更改也是局部变量"使用Lisper(Lisp用语中的措辞将是本地的绑定").

您可以通过使用函数参数(例如您的示例)或使用一些标准形式(例如:

)来创建局部变量
  • (let ((x 12)) ...)
  • (do ((x 0 (1+ i))) ...)
  • (dotimes (x 10) ...)
  • (loop for x from 0 to 10 do ...)

另一方面,有可能在您的实现中,所有局部变量都是使用参数创建的,而其他形式只是宏扩展而已.例如:

(let ((x 10)) ...)

等同于

(funcall (lambda (x) ...) 10)

还请注意,确实在读取您的代码片段时,x在某种意义上可能是全局变量",因为它可能已被声明为特殊:

(defvar x 12)
;; ==> x

(defun bar ()
  (format t "The value of x is ~a" x))
;; ==> bar

(defun foo (x)
  (bar))
;; ==> foo

(foo 42)
The value of x is 42
;; ==> NIL

x
;; ==> 12

如果使用(defvar ...)声明变量特殊",则将以不同的方式进行处理:就像每次将其用作参数或以(let ..)形式使用它一样,代码将执行的操作是保存当前值,请使用提供的新值,然后在退出函数或let后还原该值.

因此这些变量既是全局"变量(因为外部函数可以看到它们),又是局部变量(因为在函数或let终止之后,将恢复先前的值).

标准约定是使用耳罩"来命名特殊变量,即在名称的开头和结尾都带有星号,例如:

(defvar *x* 12)

这有助于谁阅读您的代码,以了解该变量是特殊的.请注意,但这不是语言所强制要求的,任何名称都可以用于特殊变量.

与C,C ++,Java或Python中的特殊变量没有类似之处.

关于setqsetf的最后一个注释.这里的事情有些棘手,因为您需要了解较低级别的Lisp才能了解为什么需要setq的原因.如果您使用的是Common Lisp,则只需忘记setq并始终使用setf.

setf是一个宏,在需要时会扩展为setq(但是在需要时setq也可以更改为setf(符号宏),这会使新手感到困惑). /p>

您的最后一个示例是关闭"的情况.当您定义一个函数(以(lambda ...)形式命名或未命名)时,该函数可以捕获"可见的变量,并在以后使用它们.通常显示的一个更简单的情况是加法器":

(defun adder (x)
  (lambda (y) (incf x y)))

此函数返回一个函数,该函数将继续将传递的值添加到内部累加器中:

(let ((f (adder 10)))
  (print (funcall f 3))
  (print (funcall f 9))
  (print (funcall f 11)))

输出将为13(10 + 3),22(13 + 9)和33(22 + 11).

匿名函数捕获"了局部变量x,即使退出adder函数也可以使用它.在C,C ++或Java这样的语言中,当退出定义变量的范围时,局部变量将无法生存.

C ++ 11具有未命名的函数,但是仍然无法捕获变量并且无法在范围内生存(它们可以复制到未命名函数的局部变量,但这不是同一回事).

If we define a function something like

(defun foo(x)
  (setf x somevalue))

Is x defined as a local variable or global? using setf/q is setting the value to be global. if it is global can anyone tell me how to define a local variable in lisp other than let?

Thanks!

Consider the following example

(let ((x 0)) 
  (defun foo (y) 
    (when (equal x 0) (setq x y)) 
    (when (< x y) (setq x y))
    x))

when I am giving some input to foo like (foo 2) , it is returning 2 and if we execute the function again with (foo 1) it still returns 2 and (foo 3) returns 3.This is what i actually want it do.But the question is how is this possible, because if I try to access the variable x outside the function from the clisp terminal, I am unable to.If I am accessing the function again, it seems to retain the previous value of x.

thank you!

解决方案

To draw a parallel to other languages like C, C++, Java or Python what your code changes is a "local variable" even if this is not a wording that a Lisper would use (the wording in Lisp parlance would be a local "binding").

You can create local variables by using function parameters like your example does, or using some standard forms like:

  • (let ((x 12)) ...)
  • (do ((x 0 (1+ i))) ...)
  • (dotimes (x 10) ...)
  • (loop for x from 0 to 10 do ...)

On the other hand it is possible that in your implementation all local variables are created using parameters and other forms simply are macros expanding to that. For example:

(let ((x 10)) ...)

is equivalent to

(funcall (lambda (x) ...) 10)

Note also that indeed reading your code fragment it's possible that x is in a sense a "global variable" because it could have been declared special:

(defvar x 12)
;; ==> x

(defun bar ()
  (format t "The value of x is ~a" x))
;; ==> bar

(defun foo (x)
  (bar))
;; ==> foo

(foo 42)
The value of x is 42
;; ==> NIL

x
;; ==> 12

If you declare a variable "special" using (defvar ...) it will be handled differently: it's like every time you use it as a parameter or you use it in a (let ..) form what the code will do is saving the current value, using the new provided value and then restoring the value after you exit the function or let.

So those variables are both "global" (because outer functions can see them) but also local (because after your function or let terminates the previous value will be restored).

The standard convention is to name special variables with "earmuffs" i.e. with an asterisk both at the start and at the end of the name like:

(defvar *x* 12)

This helps who reads your code to understand that the variable is special. Note that however this is not mandated by the language and any name can be used for a special variable.

There is nothing similar to special variables in C, C++, Java or Python.

One last note about setq and setf. Things are a bit tricky here because you need to understand lower levels of Lisp to see why setq is needed. If you are using Common Lisp then you should simply forget about setq and always use setf.

setf is a macro that will expand to setq when needed (however also setq can change into setf when needed (symbol macros) and this is where things may get confusing for a newbie).

Your last example is a case of a "closure". When you define a function (either named or unnamed with a (lambda ...) form) the function can "capture" the variables that are visible and use them later. A simpler case often shown is the "adder":

(defun adder (x)
  (lambda (y) (incf x y)))

this function returns a function that will keep adding the passed value to an internal totalizer:

(let ((f (adder 10)))
  (print (funcall f 3))
  (print (funcall f 9))
  (print (funcall f 11)))

the output will be 13 (10 + 3), 22 (13 + 9) and 33 (22 + 11).

The anonymous function "captured" the local variable x and can use it even after exiting the adder function. In languages like C, C++ or Java a local variable cannot survive when you exit the scope that defined the variable.

C++11 has unnamed functions, but still variables cannot be captured and survive the scope (they can be copied to local variables of the unnamed function, but this is not the same thing).

这篇关于LISP本地/全局变量分配的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆