Ecosyste.ms: Awesome
An open API service indexing awesome lists of open source software.
https://github.com/glittershark/pubmethod
Synchronous static publish/subscribe in Clojure(script)
https://github.com/glittershark/pubmethod
Last synced: 2 days ago
JSON representation
Synchronous static publish/subscribe in Clojure(script)
- Host: GitHub
- URL: https://github.com/glittershark/pubmethod
- Owner: glittershark
- License: mit
- Created: 2017-03-19T00:11:46.000Z (almost 8 years ago)
- Default Branch: master
- Last Pushed: 2017-03-19T22:20:07.000Z (almost 8 years ago)
- Last Synced: 2024-12-10T04:56:35.583Z (30 days ago)
- Language: Clojure
- Homepage:
- Size: 9.77 KB
- Stars: 3
- Watchers: 3
- Forks: 0
- Open Issues: 0
-
Metadata Files:
- Readme: README.md
- License: LICENSE
Awesome Lists containing this project
README
# Pubmethod
Synchronous static publish/subscribe in Clojure(script)
## Rationale
In my experience, I've encountered two primary use-cases for Clojure's
[multimethods][]:1. The same conceptual action taken on different "types" of argument, ie
conversion to a type, pretty-printing, etc. This is analogous to traditional
OOP interfaces, but superior because implementations can be defined in a
different place than the type, and the method used for determining dispatch
can be customized.
2. An event occurring, and various places in the code wanting to perform some
sort of impure (side-effectful, we don't care about the return value) action
in response to that event. The first time I ran into this was handlers for
[sente][] channel events, but it happens all over the placeMultimethods are really good at the first one - it's what they were designed
for, and it's the way clojure.core and other core libraries use them all the
time. However, they fall short on the second use-case, primarily because they
lock you in to defining one and exactly one handler for a given dispatch value.This library is intended to be a drop-in replacement for Clojure multimethods,
with support for defining more than one handler per dispatch value.[multimethods]: https://clojure.org/reference/multimethods
[sente]: https://github.com/ptaoussanis/sente## Usage
If you haven't already, read the [documentation for multimethods][mm-doc]. This
section assumes at least a passing understanding of how multimethods work.[mm-doc]: https://clojure.org/reference/multimethods
First, require the namespace
```clojure
(require '[glittershark.pubmethod :refer [defpub defsub]])
````defpub` is analogous to `defmulti`, and `defsub` is analogous to `defmethod`.
In the default case, the arguments are the same and they work the same:```clojure
(defpub foo :id)
(defsub foo :a [_] :a-called!)
(defsub foo :b [{:keys [some-arg]}] some-arg)
(defsub foo :default [_] :default-handler)(foo {:id :a}) ;; => :a-called!
(foo {:id :b, :some-arg :foobar}) ;; => :foobar
(foo {:id :unknown}) ;; => :default-handler
```Just like with `defmethod`, registering a handler for the same dispatch value
twice will overwrite the first:```clojure
(defsub foo :a [_] :overwritten!)
(foo {:id :a}) ;; => :overwritten!
```If you want to define auxiliary handlers for the same dispatch value, each
distinct handler has to be given a unique key:```clojure
(defsub foo :b :my-aux-handler [_]
(println "hello from auxiliary handler!"))(foo {:id :b, :some-arg 1})
;; prints "hello from auxiliary handler"
;; returns 1
```Just like with the primary handler, registering the same auxiliary handler twice
will overwrite the first. Also notice that the return value is the return value
of the primary handler.If a dispatch value has *only* auxiliary handlers and no primary, the return
value of a call to the pubmethod will be `nil`.## Caveat
Pubmethod currently provides no guarantee as to the order that handlers are
executed, so you should avoid writing code that relies on order. If this is a
deal-breaker for you, please feel free to report an issue.## License
Copyright © 2017 Griffin Smith. Distributed under the MIT License