Lisp中的变量引用 [英] Variable references in lisp

查看:254
本文介绍了Lisp中的变量引用的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

另一个新手(通用)LISP问题:

Another newbie (Common) LISP question:

基本上,在大多数编程语言中,函数都有一种手段来接收对变量的引用,而不是仅接收值,即,按引用传递而不是按值传递.假设为了简单起见,我想编写一个LISP函数,该函数接收一个变量并将该变量的值加1:

Basically in most programming languages there's a mean for functions to receive references to variables instead of just values, that is, passing by reference instead of passing by value. Let's say, for the sake of simplicity, I want to write a LISP function that receives a variable and increases the value of the variable by one:

(defun increase-by-one (var)
  (setf var (+ var 1)))

现在显然问题是该函数仅增加堆栈上变量的副本的值,而不是实际的原始变量.我也曾尝试通过使用宏来达到这种效果,但没有太大的成功,尽管我感觉使用宏是正确的方法.

Now obviously the problem is that this function only increases the value of the copy of the variable on the stack, not the actual original variable. I've also tried to achieve the effect by using macros without much success, although I have this feeling that using macros is the right way to go.

我一直在LISP中碰壁,我敢肯定一定有办法解决它,或者也许有完全不同的方法来解决LISP中我没有想到的这个问题? LISP如何完成这样的事情?

I hit this wall all the time in LISP and I'm sure there must be a way around it or maybe there's a completely different approach to this problem in LISP I haven't thought about? How are things like this are done in LISP?

编辑:建议使用多个人使用incf.我仅使用此示例以简单的方式演示了该问题,而实际上我并不是在寻找重新实现incf.但是还是要感谢您的建议.

EDIT: Multiple people has suggested using incf. I only used this example to demonstrate the problem in a simple way, I wasn't actually looking for reimplementing incf. But thanks for the suggestions anyway.

推荐答案

在词法作用域中,不能访问不在当前作用域中的变量.您也不能直接将词法变量传递给其他函数. Lisp评估变量并传递绑定到这些变量的值.没有像对变量的一流引用那样的东西.

With lexical scope one does not have access to variables that are not in the current scope. You also cannot pass lexical variables to other functions directly. Lisp evaluates variables and passes the values bound to these variables. There is nothing like first-class references to variables.

认为功能正常!

(let ((a 1))
  (values (lambda (new-value)
            (setf a new-value)) 
          (lambda () a)))

上面的

返回两个函数.一个可以读取变量,另一个可以写入变量.

above returns two functions. One can read the variable, another one can write the variable.

让我们调用第一个函数writer和第二个函数reader.

Let's call the first function writer and the second one reader.

(defun increase-by-one (writer reader)
   (funcall writer (1+ (funcall reader))))

因此,要执行所需的操作,代码需要a)在范围内或b)可以访问范围内的功能.

So, to do what you want, the code needs a) be in the scope or b) have access to functions that are in the scope.

变量也可以是全局变量.

(defvar *counter* 1)

(defun increase-by-one (symbol)
  (set symbol (1+ (symbol-value symbol))))
  ; note the use of SET to set a symbol value

(increase-by-one '*counter*)

这适用于用符号表示的全局变量.它不适用于词汇变量-这些变量不能用符号表示.

This works for global variables that are represented by a symbol. It does not work for lexical variables - these are not represented by a symbol.

还有一个宏INCF可以增加一个位置"(例如变量).

There is also a macro INCF that increases a 'place' (for example a variable).

(incf a)

但是a是当前作用域中的变量.

But a is the variable in the current scope.

(defun foo (a)
  (incf a))  ; increases the local variable a

可以在此处看到限制:

(defun foo (var)
  (add-one-some-how var))

(let ((a 1))
   (foo something-referencing-a))

无法将a的直接引用传递给FOO.

There is no way to pass a direct reference of a to FOO.

唯一的方法是提供一个功能.我们还必须重写FOO,以便它调用提供的功能.

The only way is to provide a function. We also have to rewrite FOO, so that it calls the provided function.

(defun foo (f)
  (funcall f 1))   ; calls the function with 1

(let ((a 1))
   (foo (lambda (n)
          (setf a (+ a n)))))
   ;; passes a function to foo that can set a

这篇关于Lisp中的变量引用的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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