defun, core.match, tagged vectors - seems like I can emulate Elixir function pattern match behaviour. I took some simple code I found online (https://twitter.com/Xzilend/status/640282621042233344) and rewrote it to 1) use only tagged vectors (not quite) and 2) use defun and tagged vectors. I am eager to hear your thoughts on the rewrite.
Original (defn- register [db mailer email password] (if (users/valid? email password) (if (users/taken? db email) (response/bad-request {:errors [{:message "That email is taken."}]}) (do (users/do-create! db email password) (users/notify mailer email activate-subject activate-text) (response/ok (auth/authenticate email)))) (response/bad-request {:errors [{:message errors/invalid-creds}]}))) Lets ignore the possible concurrency issues for now. Rewrite without using core.match (defn register ([db mailer email password] (register [:start {:db db :mailer mailer :email email :password password }])) ([status {:keys [db mailer email password] :as args}] (cond (= status :start) (if (users/valid? email password) (register [:check-unique args]) (register [:err {:res "Invalid credentials"}])) (= status :check-unique) (if (users/taken? db email) (register [:create args]) (register [:err {:res "User already exisits"}])) (= status :create) (do (users/do-create! db email password) (users/notify mailer email activate-subject activate-text) (register [:ok {:res (auth/authenticate email)}])) (= status :ok) (response/ok (:res args)) (= status :err) (response/bad-request {:errors [{:message (:res args )}]})))) With no pattern matching I had to wrap the actual arguments into a map so that all recursive calls hit the two argument arity. Using defun and tagged vectors, (defn register [& args] (register' (into [:start] args))) (defun- register' ([:start db mailer email password] (if (users/valid? email password) (register' [:check-unique db mailer email password]) (register' [:err "Invalid credentials"]))) ([:check-unique db mailer email password] (if (users/taken? db email) (register' [:create db mailer email password]) (register' [:err "User already exists"]))) ([:create db mailer email password] (do (users/do-create! db email password) (users/notify mailer email activate-subject activate-text) (register' [:ok (auth/authenticate email)]))) ([:ok res] (response/ok (:res args))) ([:err msg] (response/bad-request {:errors [{:message (:res args)}]}))) I couldn't find a way to refer to the arguments vector from within the body of a case. I would have preferred writing the :start case like this, ([:start _ _ email password] (if (users/valid? email password) (register' (into [:check-unique] it) (register' [:err "Invalid credentials"]))) I find the defun version better compared to the plain if else version. Step transitions are explicit. Early exit is a transition to err state. The `response/bad-request` call occurs only once as opposed to at each early exit point. -- 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.