如何向 cl-defmethod 添加一个新的专门化程序以应用于多个主要模式?

How to add a new specializer to cl-defmethod apply to multiple major-modes?

如何扩展 cl-defmethod 以匹配多个 major-mode? 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))

我希望 (my-gen-fun arg) 仅在 c-modec++-mode 中打印 "c-",而不是其他 cc 派生模式,如 java-modeawk-mode。如何添加新的专家来处理这种情况?

&context%optional 相似,因为它也适用于所有后续参数,因此它必须在参数之后。

但是 (major-mode <foo>-mode) 这个东西并没有像您建议的那样扩展到 (major-mode <foo>-mode <bar>-mode)(尽管它确实是一个自然的扩展)。因此,您必须调用 cl-defmethod 两次。如果正文很大,你应该把它放在一个单独的函数中:

(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 的本地补丁,它添加了您建议的 "multiple major modes" 功能,但在查看它之后我发现它有点像 hack,并引入了各种极端情况问题。

一些极端案例问题与 CLOS 不提供类似 orand 专业化程序的事实有关,例如:

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

这是因为它可以 "impossible" 找到适用方法的合理顺序(例如,上面的特化器比 (x list)(x (or (eql 5) cons)) 更具体还是更不具体? ).