Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/google-sheets/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Emacs 通过Slime重新加载多种方法_Emacs_Clojure_Slime_Multimethod - Fatal编程技术网

Emacs 通过Slime重新加载多种方法

Emacs 通过Slime重新加载多种方法,emacs,clojure,slime,multimethod,Emacs,Clojure,Slime,Multimethod,在Emacs中使用Slime repl进行开发时,我在重新加载多方法时遇到问题 重新定义defmethod表单效果很好,但是如果我更改分派函数,我似乎无法重新加载defmulti表单。我想我特别添加或删除了分派函数参数 作为一种解决方法,我能够ns取消映射multimethod变量,重新加载defmulti表单,然后重新加载所有defmethod表单 这可能是Clojure实现多方法的一个“限制”,也就是说,为了提高执行速度,我们牺牲了一些活力,但是有没有什么习惯用法或开发实践可以帮助解决这个问

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

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

作为一种解决方法,我能够
ns取消映射
multimethod变量,重新加载
defmulti
表单,然后重新加载所有
defmethod
表单


这可能是Clojure实现多方法的一个“限制”,也就是说,为了提高执行速度,我们牺牲了一些活力,但是有没有什么习惯用法或开发实践可以帮助解决这个问题呢?

简单的回答是,您处理这个问题的方法是完全正确的。如果您发现自己正在更新一个multimethod,以便特别频繁地更改分派函数,(1)我认为这是不寻常的:-),(2)您可以编写一套函数/宏来帮助重新加载。我画了两个未经测试的(!)宏来帮助下面的(2)

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

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

如果确实需要,可以通过反射来更改分派fn,但这会带来语义上的问题,特别是在多线程场景中(有关构建后对
final
字段进行反射更新的信息,请参阅)

黑客(非反射) (2)的一种方法是在使用宏重新定义后,按照(未测试的)行自动重新添加方法

另一种设计是使用一个名为的宏和方法重新注册,获取多个名称和主体的序列表,并承诺在执行主体后重新注册方法;这是一张草图(同样,未经测试):

您可以用它来表示
(使用方法重新注册[my-multi-1 my-multi-2](要求:重新加载'ns1 ns2))
。不确定这是否值得失去清晰度

(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#))))
(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#))))