I write a lot of .cljc files, and I run into a problem where I have some refers at the top, some of which are only used in CLJ, some only in CLJS, and then that causes warnings about unused variables to show up.
(ns my.ns
(:require [some.namespace :refer [used-in-clj-only ;; this will give a warning about an unused var in CLJS
used-in-cljs-only ;; this will give a warning about an unused var in CLJ
used-in-both-1
used-in-both-2]]))
If I try to add a conditional it then complains about duplicate requires:
(ns my.ns
(:require
;; Now this will complain of a duplicate :require
#?(:clj [some.namespace :refer [used-in-clj-only]]
:cljs [some.namespace :refer [used-in-cljs-only]])
[some.namespace :refer [used-in-both-1
used-in-both-2]]))
I'm sure I'm missing something simple here, what's the recommended way of dealing with this?The best solution here IMHO is to stop using :refer and use :as instead.
It will also make the ns form smaller and more readable, will make any refactoring require fewer changes, will make it obvious where a symbol came from at the call site.
I would say that's a highly subjective definition of "best" 🙂.
(I do, for the record, tend to prefer using :refer as little as possible. But sometimes the brevity is worth the tradeoff of being slightly less explicit.)
To each their own of course
That's why the "IMHO". :) But also, this is pretty much as good as it gets in the context of the OP, with reader conditionals.
> But also, this is pretty much as good as it gets in the context of the OP, with reader conditionals. That surprises me...I would think this is a common enough need that there must be some solution
Why is using :as not a solution?.. Oh, it also reduces the number of reader conditionals you have to use.
Alternatively, you can wrap every single conditional item inside :refer [...] into its own reader conditional. And use a splicing reader conditional, something like [some.namespace :refer [#?@(:clj [clj-only1 clj-only2] :cljs [cljs-only1 cljs-only2]) common1 common2]]. But boy is that ugly. :D
Just in case, a couple of things:
• You don't even need to use :as, you can just require [some.namespace] and use it as some.namespace/...
• Aliases can have dogs, so you can have [some.namespace :as some.ns]
BTW this: >
;; Now this will complain of a duplicate :require
likely comes from your IDE or something else. Definitely not from Clojure itself. So maybe another solution here is to change the configuration of that something so it stops complaining.(ns my.ns
(:require [some.namespace :refer [#?(:clj used-in-clj-only) ;; this will give a warning about an unused var in CLJS
#?(:cljs used-in-cljs-only) ;; this will give a warning about an unused var in CLJ
used-in-both-1
used-in-both-2]]))
is what I would do. the comment behind it almost begs for it.@borkdude y'know it did not occur to me that that would work. But I guess it makes sense, a single form is a single form.
react