在elisp中捕获错误案例的最佳方法是什么

时间:2012-07-20 11:47:09

标签: emacs elisp

我正在尝试增加etags-select函数,以便在点处的find-tag失败时它会回退到正常的find-tag。我试过的代码是:

(defun my-etags-find-tag ()
  "Find at point or fall back"
  (interactive)
  (unless (etags-select-find-tag-at-point)
    (etags-select-find-tag)))

(global-set-key (kbd "C-f") 'my-etags-find-tag)

但是当 point 不在有效标签时,这会失败。相反,我得到了etags-select-find-tag-at-point抛出的错误:

etags-select-find-tag-at-point: Wrong type argument: char-or-string-p, nil

在这种情况下,我只需要重复 etags-select-find-tag-at-point 所做的测试:

(defun my-etags-find-tag ()
  "Find at point or fall back"
  (interactive)
  (if (find-tag-default)
      (etags-select-find-tag-at-point)
    (etags-select-find-tag)))

但它似乎有点多余。是否可以捕获异常并在elisp中执行备用处理?

2 个答案:

答案 0 :(得分:11)

尝试ignore-errors;例如,

(unless (ignore-errors (etags-select-find-tag-at-point))
  (etags-select-find-tag))

通常情况下,(ignore-errors body)会返回body次返回的内容。当出现错误时,它会返回nil

另请查看condition-case以了解更多一般情况。

如果您安装了Elisp信息手册,您可以从中获取更多详细信息 C-H 取值 ignore-errors

编辑:

我没有考虑到该功能可能在成功时返回零;所以我们可能需要

(unless (ignore-errors (or (etags-select-find-tag-at-point) t))
  (etags-select-find-tag))

答案 1 :(得分:4)

如果不修改etags-select.el的原始源代码,我认为它是更合理的选项,即使它调用find-tag-default两次也是如此。您可以在通话中欺骗动态环境,以避免重复通话,方法是将其记忆为:

(defun my-etags-find-tag ()
  "Find at point or fall back"
  (interactive)
  (let ((ftd (find-tag-default)))
    (flet ((find-tag-default () ftd))
      (if (find-tag-default)
          (etags-select-find-tag-at-point)
        (etags-select-find-tag)))))

编辑:根据您的要求,可以解释代码。首先,请注意此代码可以解决这两个问题:

  1. 不会失败
  2. 它比您显示的代码更有效(您说它是多余的代码)。
  3. 为什么效率更高?您的冗余代码的问题在于,您致电find-tag-default以查看它是否为nil,如果是,则致电etags-select-find-tag-at-point。此函数再次调用find-tag-default以获取默认值。我的代码所做的是通过仅仅是您计算的值重新定义函数来缓存find-tag-default的值。 flet执行此操作,因此当etags-select-find-tag-at-point调用find-tag-default时,将返回计算出的值,而不进行任何进一步处理。