(defun my-blah (str)
(rx (+ (eval (substring str 1)))))
对该代码的评估将以下消息放入消息缓冲区:
Eager macro-expansion failure: (void-variable str)
这是什么意思,需要担心什么?
该功能似乎工作正常。另一方面,对以下代码的评估不会产生这样的消息:
(defvar my-str "oink")
(rx (+ (eval (substring my-str 1))))
附录:在不生成此类消息的情况下定义函数的替代方法
(defun my-nah (str)
(rx-to-string `(+ ,(substring str 1))))
(defun my-llama (str)
(eval `(rx (+ ,(substring str 1)))))
答案 0 :(得分:2)
rx
是一个宏,这意味着它可以在实际评估代码之前随时进行扩展。通常,这意味着它将在编译期间进行扩展。编译在str
已知之前发生,因此rx
的扩展不能取决于str
的值。
如果你在没有编译的情况下测试它,那么宏扩展发生的时间很晚(在评估之前/期间),所以问题是隐藏的(如果使用lexical-binding
,问题将会重新出现,因为eval
将无法访问定义str
的词汇上下文。
Eager macroexpansion(24.4中的新增功能)用于在加载非编译文件时扩展宏,这提供了类似于编译代码的宏扩展行为。为了向后兼容,当在急剧的宏扩展期间发生错误时,Emacs会延迟回扩展宏(在发出警告之后)。
答案 1 :(得分:0)
如果您想轻松测试rx表达式,请使用:
(defun test-rx (test-file test-reg)
(if (get-buffer (setq test-buffer "RX"))
(kill-buffer test-buffer))
(with-temp-buffer
(insert-file-contents-literally test-file)
(goto-char (point-min))
(while
(re-search-forward test-reg nil t)
(when (match-string 0)
(let ((one (match-string 1))
(two (match-string 2)))
(if one
(progn
(pop-to-buffer test-buffer)
(goto-char (point-max))
(insert (format "Found %s and possibly %s" one two)))))))))
(defun test-rx-now (file)
"plop"
(interactive
(let (file)
(setq file (read-file-name "File to search: "))
(list file)))
(test-rx file
(rx
"$(function"
(*? anything)
(or "'" "\"")
(group
(* (not (any "'" "\"")))
".php"
)
(or "'" "\"")
(*? anything)
"})"
)))