首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >通过Slime重新加载多方法

通过Slime重新加载多方法
EN

Stack Overflow用户
提问于 2012-02-21 05:17:00
回答 1查看 261关注 0票数 3

在Emacs中使用Slime进行开发时,我遇到了重新加载多方法的问题。

重新定义defmethod表单可以很好地工作,但是如果我更改了分派函数,似乎就无法重新加载defmulti表单。我想我特别添加或删除了调度函数参数。

作为一种变通办法,我已经能够ns-unmap多方法变量,重新加载defmulti表单,然后重新加载所有defmethod表单。

这大概是Clojure实现多方法方式的一个“限制”,也就是说,我们牺牲了一些动态性来换取执行速度,但是有没有什么习惯用法或开发实践可以帮助解决这个问题呢?

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2012-02-21 08:04:19

简而言之,你处理这件事的方式是完全正确的。如果您发现自己为了频繁地更改分派函数而更新multimethod,(1)我认为这是不寻常的:-),(2)您可以编写一套函数/宏来帮助重新加载。我画了两个未经测试的(!)帮助(2)下面更多的宏。

为什么?

然而,首先简要讨论一下“为什么”。当前实现的多方法的调度函数查找不需要同步--调度fn存储在MultiFn对象的final字段中。当然,这意味着您不能只更改给定multimethod的调度函数--您必须重新创建multimethod本身。正如您所指出的,这需要重新注册所有以前定义的方法,这是一个麻烦。

当前的行为允许您在不丢失所有方法的情况下重新加载包含defmethod表单的命名空间,代价是使替换实际的多方法变得稍微麻烦一些,而这确实是您想要做的。

如果您真的愿意,可以通过反射更改调度fn,但这有问题的语义,特别是在多线程场景中(有关构造后对final字段进行反射更新的信息,请参阅Java Language Specification 17.5.3 )。

Hacks (非反射)

(2)的一种方法是在重新定义宏后自动重新添加方法,如下所示(未测试)

代码语言:javascript
复制
(defmacro redefmulti [multifn & defmulti-tail]
  `(let [mt# (methods ~multifn)]
     (ns-unmap (.ns (var ~multifn)) '~multifn)
     (defmulti ~multifn ~@defmulti-tail)
     (doseq [[dispval# meth#] mt#]
       (.addMethod ~multifn dispval# meth#))))

另一种设计方式是使用名为with-method-reregistration的宏,它接受多个名称和主体的序列,并承诺在执行主体后重新注册这些方法;下面是一个草图(同样,未经测试):

代码语言:javascript
复制
(defmacro with-method-reregistration [multifns & body]
  `(let [mts# (doall (zipmap ~(map (partial list 'var) multifns)
                              (map methods ~multifns))))]
     ~@body
     (doseq [[v# mt#] mts#
             [dispval# meth#] mt#]
       (.addMethod @v# dispval# meth#))))

你会用它来说(with-method-reregistration [my-multi-1 my-multi-2] (require :reload 'ns1 ns2))。不确定这是否值得失去清晰度。

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

https://stackoverflow.com/questions/9368533

复制
相关文章

相似问题

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