如何将协议方法转发到现有类型?

时间:2017-10-16 22:57:19

标签: clojure protocols record

如何定义从现有类型“继承”协议的新记录?

为了明确这个问题,我将通过扩展Ubergraph进行说明,但Ubergraph只是一个例子;我正在寻找通用解决方案,而不仅仅是适用于Ubergraph的解决方案。假设我想向Ubergraph添加一个全局属性graph-name。理想情况下,我可以这样做:

(defrecord named-ubergraph [g graph-name])

(extend-type named-ubergraph
  (all-the-protocols-supported-by ubergraph.core.Ubergraph)
  (call-the-same-functions-replacing-first-argument-with '(this g))

当然,我可以查看Ubergraph源代码并手动编写所有转发函数,但是as you can see here,Ubergraph满足许多协议和许多协议方法

编写如此多的样板代码听起来并不是非常简单,而且当我想要做的就是在Ubergraph上添加一个有趣的数据时,似乎需要做很多工作。什么是更好的方式?

如果您认为我看错了,请随意重新定义问题。

1 个答案:

答案 0 :(得分:1)

extend-type将现有类型扩展到给定的协议。 如果我理解正确,您希望扩展现有记录以实现某种继承。 AFAIK,没有简单的方法可以做到这一点。 但是,如果您只想添加其他字段,则可以轻松地assoc现有记录实例的附加字段:

(defprotocol Cost
  (cost [this price-list]))

(defrecord Car [name speed]
  Cost
  (cost [this price-list] (price-list (:name this))))

(def my-car (->Car "bmw" 200))
(def price-list {"bmw" 100000})

(cost my-car price-list)
;;=> 100000

(-> my-car
    (assoc :color "blue")
    (cost price-list))
;;=> 100000

更新: 我还在Clojure邮件列表上找到了这个精彩的讨论:与"继承":https://groups.google.com/forum/#!topic/clojure/mr-o9sRyiZ0

的defrecord