【问题标题】:Emacs function returns Symbol's value as variable is void:Emacs 函数返回 Symbol 的值,因为变量是 void:
【发布时间】:2016-06-23 16:09:38
【问题描述】:

我对 Emacs 还很陌生,但我知道这很危险。我从头开始构建了我的 .emacs 文件,现在将它放在一个 org 文件中。我现在正试图将它提升到一个新的水平,让我的配置对我自己更加用户友好。

我主要使用 Emacs 进行写作。书籍、博客、编剧等。我正在尝试创建一个可以打开多种模式并即时添加设置的功能。

例如,我在写作时使用 Olivetti-mode。它使文本居中。每次我都必须调整 Olivetti-set-width。我想我会喜欢并启用拼写检查器并关闭 linum 模式。

但是,每次我尝试都会收到错误:

Symbol's value as variable is void: my-writing 

谁能解释我做错了什么?我已经 google-fu'd 相当多,但我显然对我在做什么的理解存在差距。

#+BEGIN_SRC emacs-lisp
(defun my-writing ()
"Start olivetti mode, set the width to 120, turn on spell-check."
((interactive)
 (olivetti-mode)
 (setq olivetti-set-width . 120)
 (flyspell-mode)
 (global-linum-mode 0)))

(add-hook 'olivetti-mode-hook 
    (lambda () olivetti-mode my-writing t))

#+END_SRC

【问题讨论】:

    标签: variables emacs


    【解决方案1】:

    要为特定的主要模式禁用global-linum-mode,请参阅automatically disable a global minor mode for a specific major mode

    [因为olivetti-mode 是在缓冲区中已经存在的任何主要模式之后启用的次要模式,原始发布者可能希望在 locally 中关闭 linum-mode通过将(linum-mode -1) 添加到函数my-writing 的尾部来获取当前缓冲区(见下文)。然而,这个想法假设原始发布者希望在调用 my-writing 之前在当前缓冲区中激活 linum-mode。]

    第一个问题中的函数my-writing包含一组额外的括号,应该省略,并且钩子设置不正确。

    olivetti-set-width 是一个接受一个参数的函数,因此您不能使用 setq -- 参见从第 197 行开始的函数:https://github.com/rnkn/olivetti/blob/master/olivetti.el setq 在设置变量时使用,不是 一个函数。

    虽然flyspell-mode 通常是缓冲区本地的,但最好养成使用1 参数打开次要模式或-10 来打开它的习惯离开。省略参数时,调用次要模式将作为开/关切换。

    除非已经附加到olivetti-mode-hook 的其他项目需要优先级或特殊原因需要使用具有缓冲区本地设置的挂钩,否则您不需要add-hook 的可选参数——即APPEND 和LOCAL。

    没有明显理由将(olivetti-mode) 作为olivetti-mode-hook 的一部分调用,该olivetti-mode-hook 在初始化次要模式的末尾自动调用,所以现在可以检查一下该模式是否已启用。 olivetti-mode-hook 包含在此示例中,以演示如何格式化其用法。但是,原始发布者应该考虑删除(add-hook 'olivetti-mode-hook 'my-writing),因为如果用户调用M-x my-writing 而不是M-x olivetti-mode,它似乎没有任何意义。在后一种情况下,钩子会很有用——即,当输入 M-x olivetti-mode 时——在这种情况下,确实不需要将 (unless olivetti-mode (olivetti-mode 1)) 作为 my-writing 的一部分。

    #+BEGIN_SRC emacs-lisp
    (defun my-writing ()
    "Start olivetti mode, set the width to 120, turn on spell-check."
    (interactive)
      (unless olivetti-mode (olivetti-mode 1))
      (linum-mode -1) ;; see comments above
      (olivetti-set-width 120)
      (flyspell-mode 1))
    
    ;; original poster to consider eliminating this hook
    (add-hook 'olivetti-mode-hook 'my-writing)
    
    #+END_SRC
    

    【讨论】:

    • 我做了所有的改变,它看起来和你的一模一样。现在我收到一个新错误:Lisp 嵌套超出了 'max-lisp-eval-depth'。
    • 我很抱歉假设olivetti-mode 是主要模式——它实际上是次要模式。我已经更新了代码 -- 请使用修改后的版本重试。
    • 有效!感谢您的帮助和解释。 (几周前我试过这个,所以我必须检查我的文件并清除所有的废话。现在它完美地工作了。)
    【解决方案2】:

    lawlist's answer 描述了你如何去做你真正想要完成的事情,但你得到的特定错误是因为 Emacs Lisp(像 Common Lisp,但不是 Scheme)是一个 Lisp-2。当您使用 defun 将符号与函数关联时,它不会使该符号(作为变量)的 成为该函数,而是使 函数 该符号函数的值。在非常简化的情况下,您会得到同样的错误:

    (defun foo ()
      42)
    
    (list foo)
    

    符号 foo 在这里作为变量没有任何价值。要获得稍后可以传递给 funcallapply 的内容,您需要使用符号 foo,例如:

    (funcall 'foo)
    ;=> 42
    

    (function foo)的形式:

    (funcall (function foo))
    ;=> 42
    

    可以简写成#'

    (funcall #'foo)
    ;=> 42
    

    您收到错误是因为:

    (add-hook 'olivetti-mode-hook 
        (lambda () olivetti-mode my-writing t))
    

    它尝试使用 my-writing 作为变量,但此时它没有变量值。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-08-28
      • 2023-04-10
      • 1970-01-01
      • 2014-02-19
      • 1970-01-01
      相关资源
      最近更新 更多