首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >在common-lisp中,如何覆盖/更改特定类型对象的求值行为?

在common-lisp中,如何覆盖/更改特定类型对象的求值行为?
EN

Stack Overflow用户
提问于 2011-06-02 18:43:24
回答 4查看 383关注 0票数 3

在common-lisp中,我想实现一个参考系统,如下所示:

假设我有:

(defclass reference () ((host) (port) (file)))

我也有:

获取并反序列化lisp对象的(defun fetch-remote-value (reference) ...)

我如何干预评估过程,以便每当评估引用对象时,都会再次获取并重新评估远程值,以生成最终结果?

编辑:

更详细地描述我想要实现的目标:

使用cl-store,我序列化lisp对象,并将它们发送到远程文件(或db或其他任何文件)进行保存。在成功存储后,我将主机、端口和文件保存在一个引用对象中。我希望,每当在引用对象上调用eval时,首先检索对象,然后对检索到的值调用eval。由于引用也可以在其他(父)对象或聚合类型中序列化,因此我可以通过modyfing eval获得免费的递归远程引用解析,这样我就不必自己遍历和解析已加载对象的子引用。

编辑:由于对象总是对自己求值,所以我的问题有点不对劲。从本质上讲,我想做的是:

我想截取符号的求值,以便当它们的值是引用类型的对象时,返回(fetch-remote-value object)的结果,而不是返回对象作为符号求值的结果。

EN

回答 4

Stack Overflow用户

回答已采纳

发布于 2011-06-02 18:56:38

简而言之:您不能这样做,除非重写函数eval并修改Lisp的编译器。评估规则是固定的Lisp标准。

在阅读完扩充的问题后编辑,我不认为你可以在这里完全透明地引用你的参考资料。在像这样的场景中

代码语言:javascript
复制
(defclass foo () (reference :accessor ref))
(ref some-foo)

调用ref的结果只是一个值;无论其类型如何,都不会考虑对其进行计算。

当然,您可以通过某种方式定义您的访问器,它可以透明地完成解析:

代码语言:javascript
复制
(defmacro defresolver (name class slot)
    `(defmethod ,name ((inst ,class))
        (fetch-remote-reference (slot-value inst ',slot))))

(defresolver foo-reference foo reference)

编辑您可以(某种程度上)使用符号宏挂接到Common Lisp的符号解析机制:

代码语言:javascript
复制
(defmacro let-with-resolution (bindings &body body) 
    `(symbol-macrolet ,(mapcar #'(lambda (form) (list (car form) `(fetch-aux ,(cadr form)))) bindings) ,@body))

(defmethod fetch-aux ((any t)) any)
(defmethod fetch-aux ((any reference)) (fetch-remote-reference any))

然而,现在事情变得相当神秘;变量不再是变量,而是神奇的符号,只是看起来像变量。例如,不能修改此宏“绑定”的变量的内容。对于这种方法,您能做的最好的事情就是为fetch-aux提供一个setf扩展,它会修改原来的位置。

票数 2
EN

Stack Overflow用户

发布于 2011-06-03 05:06:04

尽管用于lazy evaluationeobject persistence的库给您带来了一部分好处,但Common Lisp并没有提供一种可移植的方式来实现完全透明的持久化值。惰性或持久化值仍然必须显式为forced

但是,MOP可以用来实现惰性或持久性对象,并透明地强制使用槽值。它需要改变Common Lisp实现的内部结构来提供一般的透明性,所以你可以在p中潜在地保持持久值或惰性值的情况下使用(+ p 5)

票数 2
EN

Stack Overflow用户

发布于 2011-06-05 16:02:34

不可能直接更改评估机制。你需要为你的代码编写一个编译器。一种嵌入式语言。

在CLOS级别上,有几种方法可以处理它:

两个例子:

  • 编写对引用对象进行调度的函数:

(defmethod move ((对象引用)位置) (move (取消引用引用)位置))

(defmethod move ((对象汽车)位置) ...))

这会变得很难看,并且可能是通过宏自动完成的。

  • CHANGE-CLASS

CLOS对象已经具有间接性,因为它们可以更改它们的类。即使他们可能改变他们的班级,他们仍然保持他们的身份。CHANGE-CLASS正在破坏性地修改实例。

这样就可以传递引用对象,并在某个时刻加载数据,将引用对象更改为其他类,并相应地设置槽。这种更改类的操作需要在代码中的某处触发。

自动触发它的一种方法可能是一个错误处理程序,它可以捕获涉及引用对象的某些类型的错误。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/6213455

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档