-
Notifications
You must be signed in to change notification settings - Fork 20
Use function metadata to specify any Dire functionality you want to use #30
base: master
Are you sure you want to change the base?
Conversation
Turns out you can't resolve stuff that's out of the current scope. Which is obvious in retrospect.
Example of the fact that it doesn't work: dire.metadata> (apply-dire-meta! #'test-fn)
({:dire.core/supervisor-hook-key #<core$partial$fn__4190 clojure.core$partial$fn__4190@44708681>})
dire.metadata> (clojure.pprint/pprint (meta (var test-fn)))
{:arglists ([a b]),
:dire/eager-pre-hooks #{eager-pre-hook},
:dire/preconditions {:pre precondition},
:ns #<Namespace dire.metadata>,
:name test-fn,
:dire.metadata/handlers {:dire.metadata/pre-handlers [pre-handler]},
:dire.metadata/wrap-hooks [wrap-hook],
:column 1,
:dire/error-handlers {{:precondition :pre} pre-handler},
:dire.metadata/eager-pre-hooks [eager-pre-hook],
:doc "Docstring",
:dire.metadata/preconditions [precondition],
:dire/wrap-hooks #{wrap-hook},
:line 75,
:file "/Users/matthewdarling/src/dire/src/dire/metadata.clj"}
nil
dire.metadata> (test-fn 10 2)
5 (also, apologies for the probable e-mail spam, I keep seeing issues that need to be fixed before anyone else can actually try this out) |
This is a terrific idea! Thanks for contributing! I, too, wanted something along these lines. I never had time to chase it down though. I don't have time to look at this today, but I'll try to diagnose what's happening in the next few days. I think this would be a massive step forward for Dire if we can pull it off, though. Maybe try Alex Miller in #clojure if you're totally stumped. He's a pro with the innards of Clojure. :) |
@MichaelDrogalis (Tagging myself so I get email notifications, GitHub is pretty terrible about this) |
I wanted to do this as well and was disappointed when I found this on google and it wasn't working. I dived a bit deeper to see if I could figure it out myself, and it seems dire already does this? Or at least, does what I needed (and thought this was): (require '[dire.core :as dire])
(defn ^{:dire/preconditions {:not-three (fn [x] (= x 3))}} increase [x] (inc x))
(increase 3) ;=> 4
(increase 2) ;=> 3
(dire/supervise #'increase 3) ;=> 4
(dire/supervise #'increase 2) ;=> ExceptionInfo throw+: {:type :dire.core/precondition, :precondition :not-three}
(dire/hook-supervisor-to-fn #'increase) ;=> {:dire.core/supervisor-hook-key #<core$partial$fn__4228 clojure.core$partial$fn__4228@72ad15e6>}
(increase 3) ;=> 4
(increase 2) ;=> ExceptionInfo throw+: {:type :dire.core/precondition, :precondition :not-three} dire.core/eval1887/fn--1888 (core.clj:210) |
(this is currently a WIP, and only supports the features of Dire that I use personally, but I think it will be trivial to extend)
This allows the user to forget about all the
with-X
,remove-X
functions and use a single function to either add or remove anything they want attached to the function.Example usage
Rationale
I really like the separation of concerns that Dire enables, but as I was converting the project I work on to use Dire, I realized that I couldn't just add a precondition and forget about it entirely. In order to understand the possible return values of the function, I needed to look at what the handler would do with failure cases, and that made the code more difficult to reason about.
So I wanted a way to add metadata to functions in order to tell readers of the code that there was more going on besides what was visible in the current namespace.
The other issue I had was that, because I was using the mutating functions, loading the namespaces that used Dire would cause side effects, and that's not great. When I saw the example of using Dire with Component, I knew that was a better way of doing things, but I really didn't want to add/remove dozens of handlers and hooks manually.
Remaining issues
(meta (var test-fn))
, I see both the metadata that I specified, as well as the appropriate:dire/preconditions
style stuff. But running the function doesn't print out anything, in the way that it did in the mutation test file I was copying from.