I would like to enable users of the Cryogen static blog generator to override selected functions (in its compiler ns) so that they can for example provide extra data to the page being rendered. How to make this possible?
The simplest solution is to use
binding to ad-hoc override the functions of interest:
(binding [compile-tags-page my-tags-page] (compile-blog))
however, as former OOP dev, it seems “dirty” to override random functions somewhere deep in a function call though it also looks as the simplest solution.
The standard Clojure solution for supporting alternative implementations is protocols - I could modify the root function to take an implementation of a new
Compiler protocol. That is nice and clean - but the problem is that there are potentially many functions of interest but I only want to override a single one.
I could solve that by making my implementation delegate all other functions to the original impl but it still forces me to declare that for each:
(defprotocol Compiler (compile-tags-page [_]) (compile-tags [_]) (compile-posts [_]) #_etc...) (defrecord MyCompiler  Compiler (compile-tags-page [_] (do-my-staff)) (compile-tags [_] (compile-tags default-compiler)) (compile-posts [_] (compile-posts default-compiler)) #_etc...)
There must be a simple way.
They are way too flexible, I do not need so much flexibility. But it requires the least ceremony it seems, supporting selective overriding, if we leverage
:default and a single other dispatch value:
(defmulti compile-tags-page (constantly :custom)) (defmethod compile-tags-page :default [..] ...) ;; If I want to override it, I just do: (defmethod compile-tags-page :custom [..] (do-my-custom-stuff))
What do you think? Thanks!