Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Extending a library-provided protocol without impacting other users

Tags:

clojure

I'm using a 3rd-party library (clj-msgpack), and wish to extend a protocol for a type which the library also provides a handler for.

On its own, this is simple enough -- but is there any way to do this which wouldn't impact other users of this library running inside the same JVM? Something similar to a dynamic var binding (only taking effect under a given point on the stack) would be ideal.

At present, I'm doing an unconditional override but using a dynamic var to enable my modified behavior; however, this feels far too much like monkey-patching for my comfort.

For the curious, the (admitted abomination) I'm putting into place follows:

(in-ns 'clj-msgpack.core)

(def ^:dynamic *keywordize-strings*
  "Assume that any string starting with a colon should be unpacked to a keyword"
  false)

(extend-protocol Unwrapable
  RawValue
  (unwrap [o]
    (let [v (.getString o)]
      (if (and *keywordize-strings* (.startsWith v ":"))
        (keyword (.substring v 1))
        v))))
like image 862
Charles Duffy Avatar asked Nov 13 '22 20:11

Charles Duffy


1 Answers

After some thought I see two basic approches (one of which I get from you):

Dynamic binding (as you are doing it now):

Some complain that dynamic binding holds to the principal of most supprise; "what? is behaves this way only when called from there?". While I don't personally hold to this being a bad-thing(tm) some people do. In this case it exacly matches your desire and so long as you have one point where you decide if you want keywordized-strings this should work. If you add a second point that changes them back and a code path that crosses the two well... your on your own. But hey, working code has it's merits.

Inheritance:

good'ol java style or using clojure's add-hoc heirarchies you could extend the type of object you are passing around to be keywordized-string-widgewhatzit that extends widgewhatzit and add a new handler for your specific subclass. This only works in some cases and forces a different object style on the rest of the design. Some smart people will also argue that it still follows the principal of most surprise because the type of the objects will be different when called via another code path.


Personally I would go with your existing solution unless you can change your whole program to use keywords instead of strings (which would of course be my first (potentially controversial) choice)
like image 60
Arthur Ulfeldt Avatar answered Nov 15 '22 13:11

Arthur Ulfeldt