2017-10-16 103 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),它可以防止「關聯」到任意鍵。 –

相關問題