5

Google Common Lisp 样式指南说避免修改局部变量,尝试重新绑定

这是什么意思?那句话中的重新绑定是什么意思?

4

2 回答 2

9

这意味着您应该创建新变量而不是更改旧变量的值。例如,让我们看下面的代码:

(defun foo (x)
  (when (minusp x)
    (setq x (- x)))
  do something with x)

相反,应该创建一个新的绑定并使用该绑定:

(defun foo (x)
  (let ((xabs (if (minusp x)
                  (- x)
                  x)))
    do something with xabs)

这样做的原因是您将始终知道变量包含什么,因为它永远不会改变。如果您想要新值,只需使用保存该新值的变量。

现在你可能会问为什么这如此重要?嗯,有些人比其他人更喜欢这个。尤其是喜欢强调 Lisp 功能方面的人会提倡这种风格。但是,无论偏好如何,始终能够依赖变量不变的事实非常有用。这是一个可能很重要的示例:

(defun foo (x)
  (let ((function #'(lambda () (format t "the value of x is ~a~%" x))))
    (when (minusp x)
      (setq x (- x)))
    (other-function x)
    function))

然后, 的返回值FOO是一个函数,当调用它时打印 的值x。但是,该值将是x函数后面的值,即绝对值。如果函数大而复杂,这可能会非常令人惊讶。

于 2013-06-18T11:18:44.007 回答
4

I don't know Common Lisp well enough to answer with how to do this in Common Lisp, so I'm using Scheme for my example below. Suppose you're writing a function to return the factorial of a number. Here's a "modify local variables" approach to that function (you'll have to define your own while macro, but it's not hard):

(define (factorial n)
  (define result 1)
  (while (> n 0)
    (set! result (* result n))
    (set! n (- n 1)))
  result)

Here's a "rebind local variables" approach to that function:

(define (factorial n)
  (let loop ((n n)
             (result 1))
    (if (zero? n)
        result
        (loop (- n 1) (* result n)))))

In this case, loop is called with new values to rebind with each time. The same function can be written using the do macro (which, by the way, also uses rebinding, not modifying, at least in Scheme):

(define (factorial n)
  (do ((n n (- n 1))
       (result 1 (* result n)))
      ((zero? n) result)))
于 2013-06-18T11:14:43.057 回答