I have a few functions which allow me to add a channel to an a vector, lookup a channel by id or tag and send an event to a channel. The id is unique, the tag is not. What a channel is and what an event is is not important to my question, but for context a channel is a websocket channel and an event is a map which will get converted to JSON.
(def channels (atom []))
(defn register-channel! [id tag channel]
(swap! channels conj [id tag channel]))
(defn find-by-id [id]
(first (filter #(= id (first %)) @channels)))
(defn find-by-tag [tag]
(filter #(= tag (second %)) @channels))
(defn send! [channel event] ...)
This works fine, I could have stored maps in the atom instead of arrays, it might have made it a little more readable, but for now it works.
My question is around the function names and signatures for the functions to send an event to a single channel by id or multiple channels by tag.
I have a few options, initially I thought about two functions:
(defn send-event-by-id! [id event] ...)
(defn send-event-by-tag! [tag event] ...)
Simple enough. But I wasn’t too keen on the function names, the by-id
/ by-tag
suffixes didn’t feel right. I can’t articulate why.
So I thought maybe I can just have a single function which can be passed an id or tag, an id is a String and a tag is a Keyword. I would add a pre condition to register-channel!
to enforce this.
(defn send-event! [id-or-tag event]
(case (class id-or-tag)
java.lang.String (...)
clojure.lang.Keyword (...)))
This worked and I also tried a version using a multimethod:
(defmulti send-event! (fn [id-or-tag event] (class id-or-tag)))
But in the end, since I will not be adding any new identifiers I thought a multimethod was overkill and may have a performance hit.
Other options which occurred to me:
(defn send-event! [query event] ...)
(send-event! { :by-id 1 } { ... })
(send-event! { :by-tag :player } { ... })
and
(defn send-event! [key value event] ...)
(send-event! :id "1234" {...})
(send-event! :tag :player {...})
and
(defn send-event! [id event] ...)
(defn send-events! [tag event] ...)
So… are any more idiomatic for Clojure. Any comments? Am I over thinking it and should have just gone with my first thought, two functions.