The goal of the ISerializable protocol is to allow extending the serialization mechanism to custom types, via extend-protocol. For example, we can (extend-protocol ISerializable UUID (serialize [id] ...)) to implement serialization for UUIDs.
This extend-protocol call works by redefining the serialize function, i.e. creating a new function and changing the #'serialize var to point to this new object. The new function knows how to dispatch to the correct implementation for the types specified in the extend-protocol.
However, the implementation of clj-item->db-item using partial captures the value of the serialize function at the moment the namespace is loaded. Therefore, it will ignore any further extend-protocol calls - these will replaced the value referenced by the #'serialize var, but the clj-item->db-item function will still hold a reference to the original serialize function object.
To solve this, we have to ensure we always go through the #'serialize var when we run clj-item->db-item. This can be done in one of two ways:
Make partial capture the #'serialize var, instead of the value of that var:
(partial utils/name-map #'serialize)
Avoid partial altogether and just use normal function call syntax to call serialize. This will look up the serialize symbol in the faraday namespace, which will point to the #'serialize var, which in turn will point to the update serialize function object`
The goal of the
ISerializable
protocol is to allow extending the serialization mechanism to custom types, viaextend-protocol
. For example, we can(extend-protocol ISerializable UUID (serialize [id] ...))
to implement serialization for UUIDs.This
extend-protocol
call works by redefining theserialize
function, i.e. creating a new function and changing the#'serialize
var to point to this new object. The new function knows how to dispatch to the correct implementation for the types specified in theextend-protocol
.However, the implementation of
clj-item->db-item
usingpartial
captures the value of theserialize
function at the moment the namespace is loaded. Therefore, it will ignore any furtherextend-protocol
calls - these will replaced the value referenced by the#'serialize
var, but theclj-item->db-item
function will still hold a reference to the originalserialize
function object.To solve this, we have to ensure we always go through the
#'serialize
var when we runclj-item->db-item
. This can be done in one of two ways:partial
capture the#'serialize
var, instead of the value of that var:serialize
. This will look up theserialize
symbol in thefaraday
namespace, which will point to the#'serialize
var, which in turn will point to the updateserialize
function object`I choose the latter solution because it seemed easier to understand.