【问题标题】:Common Lisp: extract methods from generic functionCommon Lisp:从泛型函数中提取方法
【发布时间】:2017-07-26 02:40:02
【问题描述】:

有没有办法从 Common Lisp 中的泛型函数中提取方法列表?
例如:

(defmethod say ((self string)) ; method-0
  (format t "Got string: ~a~%" self))

(defmethod say ((self integer)) ; method-1
  (format t "Got integer: ~a~%" self))

(defmethod say ((self symbol)) ; method-2
  (format t "Got symbol: ~a~%" self))

(extract-methods-from-generic 'say) ; -> (method-0-obj method-1-obj method-2-obj)

更具体地说,我的目标是 ECL,所以如果这可以通过 C API 完成 - 没关系。
我需要这个来做下一个技巧:

(defgeneric merged-generic ())

(loop for method
      in (extract-methods-from-generic 'some-generic-0)
      do (add-method merged-generic method))
(loop for method
      in (extract-methods-from-generic 'some-generic-1)
      do (add-method merged-generic method))

【问题讨论】:

    标签: methods common-lisp clos generic-function mop


    【解决方案1】:

    通用函数generic-function-methods 可在 CLOS 中获取通用函数的所有方法(请参阅CLOS protocol),但请注意,对于问题的第二部分,您可以将方法附加到泛型函数(使用add-method)仅当该方法与任何其他泛型函数分离时(参见protocol):

    如果该方法已与某个其他通用函数相关联,也会发出错误信号。

    您可以通过包closer-mop 使用这两个功能,独立于任何实现:

    CL-USER> (ql:quickload "closer-mop") 
    ("closer-mop")
    CL-USER> (in-package :closer-mop)
    #<Package "CLOSER-MOP">
    C2MOP> (defgeneric say (x))
    #<COMMON-LISP:STANDARD-GENERIC-FUNCTION SAY #x30200176712F>
    C2MOP> (defmethod say ((self string)) ; method-0
      (format t "Got string: ~a~%" self))
    
    (defmethod say ((self integer)) ; method-1
      (format t "Got integer: ~a~%" self))
    
    (defmethod say ((self symbol)) ; method-2
      (format t "Got symbol: ~a~%" self))
    #<COMMON-LISP:STANDARD-METHOD SAY (SYMBOL)>
    C2MOP> (generic-function-methods #'say)
    (#<COMMON-LISP:STANDARD-METHOD SAY (SYMBOL)> #<COMMON-LISP:STANDARD-METHOD SAY (INTEGER)> #<COMMON-LISP:STANDARD-METHOD SAY (STRING)>)
    C2MOP> (defgeneric merged-generic (x))
    #<COMMON-LISP:STANDARD-GENERIC-FUNCTION MERGED-GENERIC #x30200181B74F>
    C2MOP> (add-method #'merged-generic (first **))
    
    #<COMMON-LISP:STANDARD-METHOD SAY (SYMBOL)> is already a method of #<COMMON-LISP:STANDARD-GENERIC-FUNCTION SAY #x30200165863F>.
       [Condition of type SIMPLE-ERROR]
    ; Evaluation aborted on #<SIMPLE-ERROR #x3020016719FD>.
    CL-USER> (let ((first-method (first (generic-function-methods #'say))))
               (remove-method #'say first-method)
               (add-method #'merged-generic first-method))
    #<COMMON-LISP:STANDARD-GENERIC-FUNCTION MERGED-GENERIC #x302000DC54DF>
    CL-USER> (merged-generic "a string")
    Got string: a string
    NIL
    

    【讨论】:

    • 好的,但是是否可以“克隆”一个方法并将其副本附加到另一个通用函数?
    • 你可以看看这个问题的答案:stackoverflow.com/questions/11067899/…
    • @Renzo 那就是克隆一个对象。他想在不破坏原件的情况下在两种通用方法之间进行合并,这是在这个答案中完成的。也许有人可以以某种方式代理它?
    猜你喜欢
    • 2022-11-17
    • 1970-01-01
    • 2012-08-13
    • 2014-10-24
    • 1970-01-01
    • 2017-10-19
    • 2020-08-16
    • 1970-01-01
    相关资源
    最近更新 更多