juji-io / editscript

A library to diff and patch Clojure/ClojureScript data structures
Eclipse Public License 1.0
485 stars 23 forks source link

Extending IType #24

Closed Outrovurt closed 3 years ago

Outrovurt commented 3 years ago

As strange as this may sound, I would like to be able to produce a diff between any two ranges, i.e. as generated by calls to (range ,,,). To give an idea of context, I am using them to produce sequences of DOM nodes which react to changes to an underlying value, which can be anything including a range. The problem is that ranges produce a value of type Range, which editscript treats as being of type :val when calling IType.get-type.

The upshot of this is that when I do perform a diff between two ranges, the resulting script contains a replacement of the entire sequence, e.g.

(e/diff (range 5) (range 10) {:algo :quick})
;;= [[[] :r (0 1 2 3 4 5 6 7 8 9)]]

even when specifying :algo :quick. Obviously for DOM nodes I don't want to replace everything.

My question is, in my own code, can I simply call the following without any repercussions?

(extend-protocol editscript.edit/IType 
   Range 
   (get-type [_] :lst))

The above certainly works, but I was wondering is there a more elegant solution?

huahaiy commented 3 years ago

I think what you are doing is exactly right. That's what extend-protocol is for and is idiomatic Clojure. I would say it is pretty elegant.

Basically, the possible diff-able concrete types are unbounded, there's no way for Editscript to anticipate them all. All we can do is to abstract out some common types like :val, :lst, :map, and then users can decide if their concrete type fits into one of them.

Outrovurt commented 3 years ago

Superb, thanks for confirming.