2017-10-16 143 views
2

如何定义从现有类型“继承”协议的新记录?如何将协议方法转发到现有类型?

为了清楚这个问题,我将以扩展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满足许多协议和许多协议的方法。

写了这么多的样板代码听起来不太合适,而且当我想要做的只是为ebergraph添加一个eensy-weensy位数据时,它看起来像很多工作。什么是更好的方法?

如果你认为我看错了,请随时重新考虑这个问题。

回答

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的邮件列表上的这个梦幻般的讨论:defrecord与“继承”:https://groups.google.com/forum/#!topic/clojure/mr-o9sRyiZ0

+0

只要与记录相关联是一个很好的见解!我知道Clojure允许这样做,但我没有想到这个问题。这立即解决了我目前的许多问题 - 使用理想的代码量:无!但是,我只是试着联合一个Ubergraph,这是行不通的。所以,我现在要解决这个问题了。 (向Ubergraph添加任意数据_is_实际上是我现在需要的主要实际原因。) –

+0

嗯,Ubergraph甚至有[case statements](https://github.com/Engelberg/ubergraph/blob/320e284a6de6adb241df5dfeb9fd6383caea659c/src/ ubergraph/core.clj#L214),它可以防止“关联”到任意键。 –

相关问题