在函数内部定义一个符号局部?

时间:2013-11-10 23:24:03

标签: emacs elisp

就像一个例子,函数内部put创建x属性及其全局值:

(defun foo ()
  (put 'spam 'x 1))

(foo)

(get 'spam 'x) ; -> 1

是否可以在本地设置符号属性?

3 个答案:

答案 0 :(得分:3)

不,因为'spam始终是相同的符号,所以无法在本地设置属性。

我不知道这是否适合您的情况,但您可以创建一个新的符号并将属性放在上面。因为该功能以外的符号不可用。

(defun foo ()
  (let ((private (make-symbol "private")))
    (put private 'x 1)
    (get private 'x)))

(foo) ;=> 1

(get 'private 'x) ;=> nil

make-symbol返回“新分配的[和]未分隔符号”,这意味着(make-symbol "private")返回的符号与全局'private和其他所有符号不同。有关更多信息,请参阅here以了解有关创建和实习符号的Emacs手册部分。

Emacs也支持buffer-local variables,虽然这不是一回事(符号的值是特定缓冲区的本地值,但符号本身及其属性仍然是全局的。)

如果您只需要在本地将值绑定到名称,您也可以使用Emacs 24对lexical binding的支持,或者,如果您使用的是旧版本,则lexical-let来自cl 1}}包(包含在Emacs中)。

答案 1 :(得分:2)

你可以在动态范围的意义上“本地”地做到这一点:

(require 'cl-lib)
(defun foo ()
  (cl-letf (((get 'spam 'x) 1))
    (get 'spam 'x)))

(foo) ; -> 1

(get 'spam 'x) ; -> nil

答案 2 :(得分:0)

虽然我不太明白你想做什么,但在我看来,你正在寻找一个闭包,即一个环境功能。为此,您必须启用词法绑定,从emacs 24.3 IIRC开始支持。要启用它,请将缓冲区局部变量lexical-binding设置为t。闭包的一个流行的例子是加法器工厂,这是一个函数,它返回一个常数加起来的函数。

(defun make-adder (constant)
  (lambda (y) (+ y constant)))

(make-adder 3)
;; As you can see a closure is a function with an environment associated
=> (closure ((constant . 3) t) (y) (+ y constant))

(funcall (make-adder 3) 2)
=> 5
(funcall (make-adder 5) 2)
=> 8

所以是的,使用闭包你可以为函数设置私有变量。