You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Emacs的init.el中触发Error running timer: (void-variable message)报错是什么原因?

报错原因

该错误是Emacs Lisp默认使用动态作用域导致的变量捕获失效问题:

  • 你写的匿名lambda内部引用了外层函数的message参数,动态作用域规则下,变量会在代码执行时的上下文查找,而非代码定义时的上下文。
  • run-at-time设置的计时器触发lambda执行时,外层的cypher/cowsayx-sclock函数已经执行完毕退出,message变量在当前执行上下文中已被销毁,因此抛出未定义变量的错误。
修复方案

下面提供3种常用的修复方案,任选一种即可:

方案1:利用run-at-time原生传参特性(兼容性最好)

run-at-time支持在执行函数后附加任意参数,执行时会自动将参数传入目标函数,不需要依赖变量捕获:

(defun cypher/cowsayx-sclock (in-minutes message)
  (interactive "nSet the time from now - min.: \nsWhat: ")
  (run-at-time (* in-minutes 60)
               nil
               (lambda (msg)
                 (message "%S" msg)
                 (shell-command (format "xcowsay %s" (shell-quote-argument msg))))
               message))

方案2:开启当前配置文件的词法作用域

在你的init.el文件最顶部添加如下局部变量声明,开启当前文件的词法作用域,lambda会自动捕获定义时的外部变量,原有代码无需修改即可正常运行:

;;; -*- lexical-binding: t; -*-

方案3:手动用lexical-let捕获变量

如果你不想修改全局的作用域配置,也可以用lexical-let手动捕获需要的变量:

(defun cypher/cowsayx-sclock (in-minutes message)
  (interactive "nSet the time from now - min.: \nsWhat: ")
  (lexical-let ((captured-msg message))
    (run-at-time (* in-minutes 60)
                 nil
                 (lambda ()
                   (message "%S" captured-msg)
                   (shell-command (format "xcowsay %s" (shell-quote-argument captured-msg)))))))

内容的提问来源于stack exchange,提问作者Achylles

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.05 12:30:02