f-string 展开后:
(macroexpand '(f-string "${username -30s}${somevar 1.2f}"))
;; =>
;; (s-format "${username -30s}${somevar 1.2f}" 'aget
;; (list
;; (cons "username -30s"
;; (format
;; (format "%%%s"
;; (if (string= "-30s" "")
;; (if s-lex-value-as-lisp "S" "s")
;; "-30s"))
;; (symbol-value
;; (intern "username")))) ;; <---
;; (cons "somevar 1.2f"
;; (format
;; (format "%%%s"
;; (if (string= "1.2f" "")
;; (if s-lex-value-as-lisp "S" "s")
;; "1.2f"))
;; (symbol-value
;; (intern "somevar"))))))
报错的就是 (symbol-value (intern "usernam")),抽出来放在 emacs -Q 下测试:
⋊> emacs --batch --eval "\
(let ((username \"John Kitchin\"))
(symbol-value (intern \"username\")))"
Error: void-variable (username)
mapbacktrace(#[1028 "!!!!B5@!A5!!!" [princ " " prin1 "(" " (" " " ")
"] 7 "
(fn EVALD FUNC ARGS FLAGS)"])
debug-early-backtrace()
debug-early(error (void-variable username))
symbol-value(username)
(let ((username "John Kitchin")) (symbol-value (intern "username")))
eval((let ((username "John Kitchin")) (symbol-value (intern "username"))) t)
command-line-1(("--eval" "(let ((username \"John Kitchin\"))
(symbol-value (intern \"username\")))"))
command-line()
normal-top-level()
Symbol’s value as variable is void: username
| Emacs | Test result |
|---|---|
| 25.1 | |
| 26.1 | |
| 27.1 | |
| 28.1 | |
| 29.0 |
我猜跟《 Emacs 变严格了? 》的原因类似,Emacs 27 开始对 let 变量做了某些限制。