0

如何扩展 acl-defmethod以匹配多个major-modes?cl-generic 中有一些文档,但我不明白泛化器宏发生了什么。

举个例子,

(cl-defgeneric my-gen-fun (arg)
  (message "%S" arg))

;; define this so it wouldn't affect other cc-derived modes, eg. java, awk, etc.
(cl-defmethod my-gen-fun (&context (major-mode c-mode c++-mode) arg)
  (message "c-%S" arg))

我只想在and(my-gen-fun arg)中打印“c-” ,而不是其他 cc 派生模式,如or 。如何添加新的专家来处理这种情况?c-modec++-modejava-modeawk-mode

4

1 回答 1

2

&context就像它也适用于所有后续的%optional参数,所以它必须在参数之后。

但是(major-mode <foo>-mode)事情并没有(major-mode <foo>-mode <bar>-mode)像你建议的那样延伸(尽管它诚然是一个自然的延伸)。因此,您必须调用cl-defmethod两次。如果 body 很大,你可能应该把它放到一个单独的函数中:

(defun my-gen-fun-c-body (arg)
  (message "c-%S" arg))

;; define this so it wouldn't affect other cc-derived modes, eg. java, awk, etc.
(cl-defmethod my-gen-fun (arg &context (major-mode c-mode))
   (my-gen-fun-c-body arg))
(cl-defmethod my-gen-fun (arg &context (major-mode c++-mode))
   (my-gen-fun-c-body arg))

我确实有一个本地补丁,cl-generic.el其中添加了您建议的“多种主要模式”功能,但在查看它之后,我发现它有点像黑客并引入了各种极端情况问题。

一些极端案例问题与 CLOS 不提供类似的东西orand类似的专家有关:

(defmethod foo ((x (or (eql 4) cons))) ...)

这是因为它可能使“不可能”找到适用方法的合理排序(例如,上述专业化器比 or 更具体(x list)还是更不具体(x (or (eql 5) cons))?)。

于 2020-02-16T16:05:14.690 回答