Makes perfect sense. Thanks!

On Mon, Aug 29, 2016 at 5:09 PM Jonathan Fischer <jonat...@mohiji.org>
wrote:

> 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 clojure@googlegroups.com
> Note that posts from new members are moderated - please be patient with
> your first post.
> To unsubscribe from this group, send email to
> clojure+unsubscr...@googlegroups.com
> For more options, visit this group at
> http://groups.google.com/group/clojure?hl=en
> ---
> You received this message because you are subscribed to a topic in the
> Google Groups "Clojure" group.
> To unsubscribe from this topic, visit
> https://groups.google.com/d/topic/clojure/LBQ_AELp0Mo/unsubscribe.
> To unsubscribe from this group and all its topics, send an email to
> clojure+unsubscr...@googlegroups.com.
> For more options, visit https://groups.google.com/d/optout.
>
-- 
Jonathon McKitrick

-- 
You received this message because you are subscribed to the Google
Groups "Clojure" group.
To post to this group, send email to clojure@googlegroups.com
Note that posts from new members are moderated - please be patient with your 
first post.
To unsubscribe from this group, send email to
clojure+unsubscr...@googlegroups.com
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 clojure+unsubscr...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

Reply via email to