I've wondered that myself. Obviously, multimethods are not optimal when it comes to doc strings/IDE support, and the fact that they're isolated (as data) from usage site makes it even worse.
My goal would be to find a way to get tools to tell me what mutations were available and how they are used. Can individual multimethod instances have metadata?
actually, your solution of :doc is nice, in that the functions should be side-effect free, meaning you can make a tool to dump the doc that just calls the function
maybe i should re-ask this in #om ?
It is a valid question for them, yes...and there are 10x the ppl there. Perhaps someone has a suggestion.
@mitchelkuijpers Thanks for the heads up. This might affect us, but it seems primarily an issue with re-rendering. I'll have to look it over mroe carefully.
@tony.kay in a nutshell, it's basically about not having to re-render from root whenever a remote response is merged in
@anmonteiro A remote response from a mutation? There is no default merge for such a response.
is it just queuing the component that sent the mutation?
Both from reads and mutations
And yes
oh, and also the follow-ons
ok, so an optimization
Yeah
Thanks my friend
Just to prevent having to re-read root
Np!
So the answer from Nolen himself is that there's no obvious answer. I think for now I'll just keep putting the :doc
"string"
in the return value.
@adambros: maybe something could be done by messing with the add-method
and get-method
functions
Essentially the multimethod API
But could be fragile and only work for multimethods so I don't know
@adambros Just brainstorming here: I guess you could make real namespaces/methods for the abstract mutation names, which are in turn distributed by the parsing mechanism. Real docstrings could then be used, and the IDE would probably also pick them up. The danger would then be accidentally directly calling them from the UI.
(ns myns)
(defn boo "doc" [env k params] ...)
(ns ui)
(transact! this '[(myns/boo)])
(ns mutations)
(defmethod 'myns/boo [e k p] (myns/boo e k p))
of course, the docstring in this case would be a little weird, in that you would call it differently than the signature of the method indicates.
This is a bit weirder, but you could write the signature as it should be used, then ignore the parameters in the body and instead return a function:
(defn boo "doc" [& {:keys [p1 p2]}] (fn [e k p] ...))
then in mutations
ns:
(def realboo (myns/boo))
(defmethod 'myns/boo [e k p] (realboo e k p))
something like that...with various clean-ups and removal of boilerplate. E.g. a simple macro for the last stepThis has the following advantages:
- The IDE doc function works as expected and gives correct information (though you do have to require a namespace that you don't actually use directly)
- The implementation adds almost no overhead (in fact you could inline the intermediate realboo
)
- The IDE jump-to feature actually jumps you to the correct code that really accomplishes the task
so, basically, it acts just like a regular function, while being "just data" from the UI
A macro potentially loses some of those benefits (e.g. if you generate all of that from a single macro the IDE might lose the ability to jump to the definition). Worth trying in NREPL and Cursive and see.