This question is off the back of a previous question I asked here a few days ago. One of the comments was that I should dispense with the Ring middleware for extracting query parameters and write my own. One alternative that I thought I'd play with was harnessing the existing one to get what I want and I've been doing some digging into the Ring source code. It does almost exactly what I want. If I write out how I understand it works:
params
map to the request
map, calls assoc-query-params
Associate a key with a value in a map. If the key already exists in the map, a vector of values is associated with the key.
This last function is the one that is problematic in my previous question (TL;DR: I want the map's values to be consistent in class of either a string or a vector). With my object orientated hat on I would have easily solved this by subclassing and overriding the method that I need the behaviour changed. However for Clojure I cannot see how to just replace the one function without having to alter everything up the stack. Is this possible and is it easy, or should I be doing this another way? If it comes to it I could copy the entire middleware library and the codec one, but it seems a bit heavyweight to me.
While a custom middleware is probably the clearest way to go for this problem, don't forget that you can always override any function using with-redefs. For example:
(ns tst.demo.core
(:use tupelo.core tupelo.test))
(dotest
(with-redefs [clojure.core/range (constantly "Bogus!")]
(is= "Bogus!" (range 9))))
While this is primarily used during unit tests, it is a wide-open escape hatch that can be used to override any function.
To Clojure, there is no difference between a Var in your source code versus one in a library (or even clojure.core
itself, as the example shows).