举个例子,put
在函数内部全局创建x
属性及其值:
(defun foo ()
(put 'spam 'x 1))
(foo)
(get 'spam 'x) ; -> 1
有没有办法在本地设置符号属性?
不,因为'spam
始终是相同的符号,所以不能在本地设置属性。
我不知道这是否适合您的情况,但您可以创建一个新符号并将属性放在上面。因为符号在函数之外不可用,属性也不可用。
(defun foo ()
(let ((private (make-symbol "private")))
(put private 'x 1)
(get private 'x)))
(foo) ;=> 1
(get 'private 'x) ;=> nil
make-symbol
返回一个“新分配的 [and] uninterned 符号”,这意味着返回的(make-symbol "private")
符号与全局符号'private
和所有其他符号不同。有关更多信息,请参见Emacs 手册中有关创建和实习符号的部分。
Emacs 还支持缓冲区局部变量,尽管这并不完全相同(符号的值对于特定缓冲区是局部的,但符号本身及其属性仍然是全局的)。
如果您只需要在本地将值绑定到名称,您还可以使用 Emacs 24 对词法绑定的支持,或者,如果您使用的是旧版本,则lexical-let
可以使用cl
包中的(包含在 Emacs 中)。
您可以在动态范围的意义上“本地”执行此操作:
(require 'cl-lib)
(defun foo ()
(cl-letf (((get 'spam 'x) 1))
(get 'spam 'x)))
(foo) ; -> 1
(get 'spam 'x) ; -> nil
虽然我不太明白你想要做什么,但在我看来你正在寻找一个闭包,即一个带有环境的函数。为此,您必须启用从 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
所以是的,使用闭包你可以为函数设置私有变量。