clojure - 通过“匿名”协议和方法将类型/fn 对融合为多态 fn
问题描述
我的目标是一个像这样工作的函数/宏:
(def f (polymorphic-fn
java.lang.Long (fn [a] (inc a))
java.lang.String (fn [a] (str a "x"))))
(f 1) ;; => 2
(f "abc") ;; => "abcx"
由于基于类型的协议分派具有最佳性能,我正在考虑使用如下宏为“融合”函数创建一个“匿名”协议:
(defmacro polymorphic-fn
[& pairs]
(let [proto (gensym)
method (gensym)
extends (for [[type handler] pairs]
`(extend ~type ~proto {(keyword ~method) ~handler}))]
`(do
(defprotocol ~proto (~method [e#]))
~@extends
~method)))
这会产生错误:Unable to resolve symbol: G__18707
。
有没有办法返回“匿名”方法,还是有更好的方法来实现这样的功能?
解决方案
问题是defprotocol
它将生成将实习协议方法的代码。IE。在宏扩展之后,编译器仍然不知道您定义的方法的符号。因此,编译失败并且会抱怨符号是未知的。
许多其他def...
's 将生成一个宏“调用”,该宏“调用”将在宏扩展期间实习符号(因此编译器将保持满意)。
要修复它,您可以事先声明它。这是可行的,因为declare
它是宏,会被扩展并且编译器会很高兴:
(defmacro polymorphic-fn
[& pairs]
(let [proto (gensym "proto")
method (gensym "prot-method-")
extends (for [[type handler] (partition 2 pairs)]
`(extend ~type ~proto {~(keyword (str method)) ~handler}))]
`(do
(declare ~method)
(defprotocol ~proto (~method [e#]))
~@extends
~method)))
注意:我也修复了这个keyword
调用。
推荐阅读
- django - 如何将值插入相关模型?
- jupyter-notebook - 禁止在 Jupyter Notebook PDF 导出中打印单元格
- android - 在约束布局中是否可以将 4 个 TextViews 放在一个水平链中,每个视图之间的空间不同?
- tensorflow - 为什么我的卷积实现比 Tensorflow 的慢?
- sql - SQL如何设置这个where子句来检查两个不同的字段?
- python - 在 IPython 控制台中运行内核的问题
- python - 如何在python(tkinter)中捕获窗口后面的图像
- google-cloud-platform - 我无法在谷歌云平台上发布 .net core 3.0 版本
- asp.net-core - Ocelot 网关:没有这样的主机是已知的
- azure - Azure DevOps 代理作业自动选择池:'Hosted Ubuntu 1604'