Skip to content

Instantly share code, notes, and snippets.

@kendru
Created November 18, 2019 00:51
Show Gist options
  • Save kendru/93fa0a2472b8ea658f8d9283701e7c65 to your computer and use it in GitHub Desktop.
Save kendru/93fa0a2472b8ea658f8d9283701e7c65 to your computer and use it in GitHub Desktop.
Emulating Objects in Clojure(Script)
(defn make-mailbox
([] (make-mailbox {:messages []
:next-id 1}))
([state]
{:deliver!
(fn [msg]
(make-mailbox
(-> state
(update :messages conj
(assoc msg :read? false
:id (:next-id state)))
(update :next-id inc))))
:next-unread
(fn []
(when-let [msg (->> (:messages state)
(filter (comp not :read?))
(first))]
(dissoc msg :read?)))
:read!
(fn [id]
(make-mailbox
(update state :messages
(fn [messages]
(map #(if (= id (:id %)) (assoc % :read? true) %)
messages)))))}))
(defn call [obj method & args]
(apply (get obj method) args))
(loop [mbox (-> (make-mailbox)
(call :deliver! {:subject "Objects are Cool"})
(call :deliver! {:subject "Closures Rule"}))]
(when-let [next-message (call mbox :next-unread)]
(println "Got message" next-message)
(recur
(call mbox :read! (:id next-message)))))
;; Got message {:subject "Objects are Cool", :id 1}
;; Got message {:subject "Closures Rule", :id 2}
;; Read all messages!
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment