lisp - lisp 中的变量引用

标签 lisp common-lisp

另一个新手(常见)LISP 问题:

基本上在大多数编程语言中,函数都有一种方法接收对变量的引用而不仅仅是值,即通过引用传递而不是通过值传递。比方说,为了简单起见,我想编写一个 LISP 函数来接收一个变量并将该变量的值增加 1:

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

现在很明显的问题是,这个函数只增加了堆栈上变量副本的值,而不是实际的原始变量。我也曾尝试通过使用宏来实现这种效果,但没有取得太大成功,尽管我觉得使用宏是正确的方法。

我在 LISP 中一直遇到这堵墙,我确信一定有解决方法,或者在 LISP 中可能有一种我没有想过的完全不同的方法来解决这个问题? LISP 中是如何完成这样的事情的?

编辑:多人建议使用incf。我只是用这个例子以简单的方式演示问题,我实际上并不是在寻找重新实现 incf。但无论如何还是感谢您的建议。

最佳答案

在词法作用域中,不能访问不在当前作用域中的变量。您也不能将词法变量直接传递给其他函数。 Lisp 评估变量并传递绑定(bind)到这些变量的值。没有什么比对变量的一流引用更好的了。

思考功能!

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

上面返回了两个函数。一个可以读取变量,另一个可以写入变量。

我们将第一个函数称为writer,将第二个函数称为reader

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

因此,要执行您想要的操作,代码需要 a) 在范围内或 b) 可以访问范围内的函数。

变量也可以是全局的

(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*)

这适用于用符号表示的全局变量。它不适用于词法变量——这些变量不是用符号表示的。

还有一个宏 INCF 增加一个“地方”(例如一个变量)。

(incf a)

但是a是当前范围内的变量。

(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

唯一的办法就是提供一个函数。我们还必须重写 FOO,以便它调用提供的函数。

(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 - lisp 中的变量引用,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/22596635/

相关文章:

javascript - 什么是具有以下类型签名的函数 : (x) => (func) => (. ..values) => func(x,...values)

lisp - elisp:数字不能大于(expt 2 60)?

common-lisp - 匿名 CLOS 实例

common-lisp - FORMAT 是否为列表迭代提供计数器

optimization - 通用 Lisp : Optimizing file parsing for minimum reads and memory allocations

windows - Clozure 普通口齿不清。如何在 Windows 上列出子目录?

lisp - Common Lisp 中有函数原型(prototype)吗?

lisp - lisp中的开关盒

format - 漂亮地打印固定宽度字段中的值

optimization - 是否可以为单个包声明优化?