The most straightforward one: just make your protocols a thing that your
storage medium implements, instead of your records. E.g.:
(defprotocol ThingStore
(load-item [store item-id])
(load-items [store item-ids])
(find-item [store item-name])
(save-item [store item]))
(defrecord DatabaseStore
ThingStore
(load-item [store item-id] ...))
Otherwise, Clojure does have multimethods, but the dispatch mechanism
doesn't work the same was as Common Lisp's. You could probably combine
multimethods with a marker protocol to do what you're trying.
;; First, an empty marker protocol
(defprotocol Loadable)
;; And something that you want to load
(defrecord Thing [data]
Loadable ;; mark that it implements that empty protocol
)
;; Define a multimethod dispatch function that will figure out the right
implementation to call
(defn loadable-dispatch
[item]
(cond (satisfies? Loadable item) ::load-one-item
(and (sequential? item) (every? #(satisfies? Loadable %) item))
::load-many-items
:else nil))
;; The multimethod itself
(defmulti load-item loadable-dispatch)
;; And implementations
(defmethod load-item ::load-one-item
[item]
"Load one item.")
(defmethod load-item ::load-many-items
[items]
"Load many items.")
user> (load-item (map->Thing {}))
"Load one item."
user> (load-item [(map->Thing {}) (map->Thing {})])
"Load many items."
Overall, you're probably better off with the first option, but you can make
multimethods work for you here if you want.
On Sunday, August 28, 2016 at 7:29:46 AM UTC-7, Jonathon McKitrick wrote:
>
> I'm beginning a foray into protocols after coming from the Common Lisp
> world of multimethods. I'm using them initially to implement a consistent
> load/save API over the DB layer.
>
> It's pretty simple to have a Saveable protocol to save one object, because
> the first argument is a Record of the type I am saving.
>
> But since protocols dispatch on the first argument, how do you define a
> Loadable protocol that loads an object or handles a collection of objects?
>
> For example, if I want to load an object by idx, the first argument is not
> a Record, but an integer, or perhaps an arbitrary field to used in a query.
>
>
>
--
You received this message because you are subscribed to the Google
Groups "Clojure" group.
To post to this group, send email to [email protected]
Note that posts from new members are moderated - please be patient with your
first post.
To unsubscribe from this group, send email to
[email protected]
For more options, visit this group at
http://groups.google.com/group/clojure?hl=en
---
You received this message because you are subscribed to the Google Groups
"Clojure" group.
To unsubscribe from this group and stop receiving emails from it, send an email
to [email protected].
For more options, visit https://groups.google.com/d/optout.