6

我正在尝试增强 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)

但是,当不在有效标签上时,这会失败。相反,我收到了 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 中捕获异常并进行替代处理?

4

2 回答 2

12

试试ignore-errors;例如,

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

通常,(ignore-errors body)返回任何body返回;当有错误时,它返回nil

另请查看condition-case更一般的条件处理。

如果您安装了 Elisp 信息手册,您可以从 C-hSignore-errors.

编辑:

我没有考虑到函数成功返回 nil 的可能性;所以我们可能需要

(unless (ignore-errors (or (etags-select-find-tag-at-point) t))
  (etags-select-find-tag))
于 2012-07-20T13:49:01.760 回答
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. 它比您显示的代码(您说它是多余的代码)更有效。

为什么效率更高?您的冗余代码的问题在于您调用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,计算的值会被返回而不做任何进一步的处理。

于 2012-07-20T12:12:03.160 回答