【问题标题】:How can I get a variable's initial value in Elisp?如何在 Elisp 中获取变量的初始值?
【发布时间】:2018-03-01 06:10:35
【问题描述】:

在 Emacs Lisp 中,是否有一个函数可以获取由defvar 初始化的符号的初始值?就像下图的some-function

(defvar var "initial value")
(setq var "changed value")
(some-function 'var)
=> "inital value"

【问题讨论】:

  • 为什么会有这样的功能?
  • @DavidThornley: gnus-sum-thread-tree-root is a variable defined in `gnus-sum.el'. Its value is "- " Original value was "> "

标签: emacs elisp


【解决方案1】:

这一般是不可能的(Emacs 不记得原来的值),但也有一些例外。

defcustom变量

使用defcustom 定义并使用自定义系统修改的变量获取原始值、保存的值和自定义但尚未保存的值作为属性:

(defcustom foo 0 "testing")
(custom-set-variables '(foo 1))
(setq foo 2)
(customize-mark-as-set 'foo)
(setq foo 3)

(car (get 'foo 'standard-value))   ;; evaluates to 0
(car (get 'foo 'saved-value))      ;; evaluates to 1
(car (get 'foo 'customized-value)) ;; evaluates to 2
foo                                ;; evaluates to 3

请参阅 elisp 手册中的 Defining Customization Variables 部分,特别是 custom-reevaluate-setting 函数文档上方的讨论。

缓冲区局部变量

缓冲区局部变量有一个默认(全局)值和一个可能与全局值不同的缓冲区局部值。可以使用default-value函数获取默认值:

(setq indent-tabs-mode nil)
(default-value 'indent-tabs-mode)  ;; evaluates to t

可以更改默认值,但是 Emacs 不会记住原来的默认值:

(set-default 'indent-tabs-mode nil)
(default-value 'indent-tabs-mode)  ;; evaluates to nil

有关详细信息,请参阅 elisp 手册中的 Introduction to Buffer-Local Variables 部分。

【讨论】:

    【解决方案2】:

    Emacs 不记得初始值。如果你评估

    (defvar var "initial value")
    (setq var "changed value")
    

    *scratch* 缓冲区中,"initial value" 不再可用,句号。

    如果defvar 在加载的文件中执行,Emacs 会记住它是从哪里加载的; (symbol-file var 'defvar) 返回文件名,假设文件仍然存在,您可以获得初始化变量的原始表达式(但不是原始值)。这也可以通过命令 M-x find-variable 获得。

    【讨论】:

    • 已接受。幸运的是,我发现所需的变量是由 defcustom 而不是 defvar 定义的。 defcustom 将符号的标准值存储在其属性列表中。
    • -1 因为这没有提到defcustom 符号属性
    • @RichardHansen 虽然这确实是一个有用的旁白,但问题是关于“defvar 初始化的符号”。 defcustom 属性如何与 defvar 初始化的符号相关?
    • @Gilles:好点;现在我希望我没有投反对票。我脑子里只有标题,没有提到defvar。但是,提及devcustom 会提高此答案的质量...
    【解决方案3】:

    如果变量设置为buffer local valuesframe local values,试试:

    (default-value 'var)
    

    不过,如果有人使用setq-default 更改默认设置,您将获得新的,而不是通过defvar 设置的原始设置。来自documentation

    此函数返回符号的默认值 价值。这是看到的价值 在没有的缓冲区和帧中 他们自己的这个变量的值。如果 符号不是缓冲区本地的,这是 等同于符号值(参见Accessing Variables)。

    【讨论】:

    • default-value 似乎返回的是缓冲区局部变量的全局值,而不是初始值。
    • @pt 是的,我立即跳到脑海中的缓冲区位置,我已经更新了答案以反映更多。
    【解决方案4】:

    看起来@tao-peng 自己在这里找到了答案,但完整的故事是这样的:

    使用defvar 创建的符号通常只有它设置的值,以及可选的属性列表,最多通常设置variable-documentationrisky-local-variable,例如:

    > (symbol-plist 'load-path)
    (risky-local-variable t variable-documentation -587478)
    

    另一方面,使用defcustom 创建的符号具有更长的symbol-plist,包括一个standard-value 属性,您可以像这样获得:

    > (get 'package-archives 'standard-value)
    ((quote (("gnu" . "http://elpa.gnu.org/packages/"))))
    

    正如@trey-jackson 所说,对于具有缓冲区本地或帧本地值的符号,您可以通过以下方式获得原始值:

    > (setq foo "bar")
    > (make-variable-buffer-local 'foo)
    > (setq foo "baz")
    > (default-value 'foo)
    "bar"
    > foo
    "baz"
    

    【讨论】:

      【解决方案5】:

      我们的解决方案:

      ;;;###autoload
      (defun xorns-get-original-value (symbol)
        "Return SYMBOL's original value or nil if that is void."
        (if (boundp symbol)
          (eval (car (get symbol 'standard-value)))))
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2010-10-07
        • 1970-01-01
        • 2019-03-10
        相关资源
        最近更新 更多