1
(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)))))
4

2 回答 2

3

rx是一个宏,这意味着它可以在实际评估代码之前的任何时候进行扩展。通常,这意味着它将在编译期间扩展。编译发生在str已知之前,因此 的扩展rx不能依赖于 的值str

如果您在不编译的情况下对其进行测试,那么宏扩展会发生较晚(就在评估之前/期间),因此问题被隐藏(如果您使用lexical-binding该问题将重新出现,因为eval将无法访问str定义的词法上下文) .

Eager macroexpansion(24.4 中新增),用于在加载非编译文件时扩展宏,提供类似于编译代码的宏扩展行为。为了向后兼容,当急切宏扩展期间发生错误时,Emacs 会延迟扩展宏(在发出您看到的警告之后)。

于 2013-09-08T16:10:06.133 回答
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)
            "})"
            )))
于 2014-08-25T14:26:06.180 回答