Common Lisp - 关于如何编写类似于“with-slots”的“with-methods”宏有什么想法吗?

问题描述 投票:0回答:1

所以我的想法是减少对对象实例的调用量,因为它显然是范围内唯一的实例。
这是一个代码示例:

(defun read-plist (plist)
    (let ((plist-reader (make-instance 'plist-reader))
        (loop for (indicator value) in plist
            do (read-indicator plist-reader indicator)
            do (read-value plist-readere value))
        plist-reader)) 

这就是我想要的样子:

(defun read-plist (plist)
    (let ((plist-reader (make-instance 'plist-reader))
        (with-methods (read-indicator (rv read-value)
                plist-reader)
            (loop for (indicator value) in plist
                do (read-indicator indicator)
                do (rv value)))
        plist-reader))

我认为这并不是最好的例子,因为它使代码看起来更加复杂。但我可以想象一种情况,它会大大减少复杂性。也许我正在寻找一个完全错误的方向,但我最初的想法是当范围明显是本地时减少名称的使用。拥有一个自己的小包,用函数取代将方法绑定到特定对象的需要,这是否是一个更好的做法?我想没有一个真正的答案,但无论如何......你对宏观有何看法? :D

我尝试以这种方式定义宏的方向:

(defmacro with-methods (methods class-instance &rest code) 
    ...) 

但看来我需要查看所有其余代码,找到给定方法的所有出现并将它们修改为列表。它给我带来了性能问题的困境。也许我错过了一种经典的方法?从 Common Lisp 初学者的角度来看,我发现文档无法搜索,只有在 ChatGPT 对其进行修改之后才可读。

oop lisp common-lisp clos lisp-macros
1个回答
0
投票

正如@Barmar 在评论中解释的那样,

with-methods
可以扩展为
flet
:

(defmacro with-methods (methods class-instance &rest body) 
    "Reduces calls to class methods down to their names and rest parameters, 
     given that the first argument to every method is class instance.
     Acts similarly to 'with-slots'.
     'methods' argument is a list of method names, that may contain
     sublists with short names like so: 
     (actual-method-name-1 (mn-2 actual-method-name-2)"

    `(flet ,(loop for method-name in methods
                 if (listp method-name)
                     collect `(,(first method-name) (&rest args)
                              (apply #',(second method-name) ,class-instance args))
                 else
                     collect `(,method-name (&rest args)
                              (apply #',method-name ,class-instance args)))
        ,@body))

其中

loop
部分负责按以下方式传递给宏的方法名称:

(method-name-1 (m-name-2 method-name-2))

我测试了代码,它的效果非常好。请原谅多次取消引用,我希望它是可读的:D

© www.soinside.com 2019 - 2024. All rights reserved.