let修改临时变量能否和autoload搭配使用

比如我有一个 test-a.el 文件

;;; test-a.el --- test.	-*- lexical-binding: t -*-

(defvar test-message "hello")

(defun test-a()
  (message test-message))

(provide 'test-a)
;;; test-a.el ends here

准备使用let临时修改test-message并调用test-a

(progn
  (autoload 'test-a (expand-file-name "test-a" user-emacs-directory))

  ;; (defvar test-message)
  (let ((test-message "world"))
    (test-a))

  (test-a))

除非手动(require 'test-a)或者let前先使用(defvar test-message), 否则会抛出错误(error "Defining as dynamic an already lexical var"),有大佬知道这是啥情况吗,有没有更好的方式解决?

defvar 是唯一正确方法。

有时候如果不想把变量设成全局 special,可以这样用 defvar

(let (_)
  (defvar test-message)
  (let ((test-message "world"))
    (test-a)))

可以用 Emacs 28 新加的 dlet macro 以写成

(dlet ((test-message "world"))
  (test-a))

但你这个例子里 test-message 不管怎樣都已是全局变量了

1 个赞

你的问题有点像这个:emacs lisp 有函数提升吗

let 刚准备好一个局部变量,autoload 插队进来说,不好意思,我们要的是一个全局变量。

let 没法预判,只能手动 defvar “提升”。