This page is not created by, affiliated with, or supported by Slack Technologies, Inc.
I've got an issue. I had a namespace where the implementation was in the same namespace as the exposed API, but made private. Now I want to switch this so that I move the impl into an impl namespace, and it's all public. That makes tests, and certain constructs that are hard to make private easier to manage. But, I have some functions that were using both other public API functions and some private impl functions. So the impl function would need to depend on the public API namespace, which in-turn depends on the impl namespace, which is circular, how can I solve this?
That's essentially what Polylith encourages: then your impl
functions can all call each other directly and your interface
functions are the pure public API (and can be written in alphabetical order!).
Hum, would you do:
(def foo impl/foo))
or
(defn foo [...]
(impl/foo ...))
Also, with the former approach, I always forget how to do it for macros or vars so that it brings along the doc-string and meta and all that too.> so that it brings along the doc-string and meta and all that too. Do you need all that in the private impl?
I can move the doc and meta to the public one I guess. But then when I work on the impl, I don't get to see the doc 😛
If it's only the docstring that you really need, you can easily "inherit" it by referencing the impl ^:doc
meta in the API meta.
Otherwise, there's stuff like Potemkin, which to me seems to be generally discouraged.
Hum, no I think you could do something like (def foo impl/foo)
and maybe also after call with-meta or vary!-meta.
You can, but you still have to filter out the right meta to avoid copying stuff like :line
.
I use a defn
(or defmacro
) wrapper -- and I write my public docstrings for users and my private docstrings for maintainers/implementations.
It'll get optimized away by the JVM...
(or if it doesn't, it's fast enough that it simply doesn't matter)
I might create a release script that just copies over the doc from the impl into the public namespace. I don't like having my doc in both places haha.
As I said, I take it as an opportunity to have user docs vs maintainer docs 🙂
Ya, I was trying that, but it's the same function, I couldn't really think what I would write different for the impl
@U2FRKM4TW What do you mean?
Oh, right, because of this: https://clojurians.slack.com/archives/CPABC1H61/p1716786113045219
Well, I decided to do this anyways, since repl based doc will work with this, just not lsp.
It's lisp, put your definition in a macro-thunk and expand it twice.
Jokes aside, I think that this is one of those things that are annoying but don't really amount to much in the grand scheme of things. Writing separate docs takes being really on top of your process but it's probably ideal to ensure full separation between layers and approachability for the code without an IDE, but I personally use my own defnwrapper
, defvarwrapper
and defmacrowrapper
macros that wrap and copy over the relevant meta because I barely touch my code without Calva spun up and worst come to worst I can jump to the private definition anyway.
There’s a feature request on clojure-lsp about supporting delegated arglists: https://github.com/clojure-lsp/clojure-lsp/issues/1811