This page is not created by, affiliated with, or supported by Slack Technologies, Inc.
2022-02-13
Channels
- # announcements (18)
- # babashka (52)
- # beginners (47)
- # calva (45)
- # clj-kondo (31)
- # clojure (18)
- # clojure-brasil (2)
- # clojure-europe (3)
- # clojure-sweden (25)
- # clojurescript (19)
- # cursive (15)
- # datalevin (11)
- # defnpodcast (2)
- # duct (1)
- # editors (1)
- # emacs (6)
- # gratitude (1)
- # introduce-yourself (6)
- # jobs-discuss (11)
- # leiningen (3)
- # lsp (10)
- # luminus (2)
- # off-topic (4)
- # podcasts (2)
- # reitit (2)
- # shadow-cljs (10)
- # sql (9)
- # xtdb (4)
is there a way to see the namespace that is currently being linted, from a hook? I am looking to suppress this error:
test/sicmutils/fdg/ch10_test.cljc::: warning: redefined var #'sicmutils.fdg.ch10-test/spherical
which happens because this form:
(define-coordinates [r theta phi] spherical)
expands into:
(let* [G__57649 (with-coordinate-prototype spherical ['r 'theta 'phi])]
(def spherical G__57649)
...)
This overwrites the spherical
binding, of course, but that’s the intent of this form.
So my thought was that my hook could just NOT emit the def if the symbol is already bound in the namespace. But maybe there is a better way to suppress?@borkdude ugh, I printed the whole thing before and didn’t see :namespace
but of course it’s here as :ns
. I’m making a strong effort to not waste your time here, I promise!!
@borkdude but while I have you, I was thinking that one nice function in a hook would be something like fmap
; the pattern of (api/token-node (f (:value node)))
, (api/list-node (f (:children node)))
etc would be instead (api/fmap f node)
in both cases
powered by a protocol offering fmap*
or something so you could correctly dispatch on the non-function arg
@borkdude it won’t quite work due to caching, I think. here is what I tried:
(defn define-coordinates [{:keys [node ns]}]
(let [[_ _ system] (:children node)
analysis (api/ns-analysis ns)
existing (into (set (keys (:clj analysis)))
(keys (:cljs analysis)))
sys-name (api/token-node (symbol (name (:value system))))
new-node (api/list-node
(concat
[(api/token-node 'do)]
(when-not (existing (:value sys-name))
[(api/list-node
[(api/token-node 'def) sys-name system])])))]
{:node new-node}))
the first time I run the linter, given some form like
(define-coordinates t e/R1-rect)
the linter runs with no warnings (but internally (def R1-rect e/R1-rect)
is emitted). So next time I run the linter, (api/ns-analysis ns)
shows that the binding exists, since the linter emitted it last time…
which means that this form will NOT be present the second time, causing error: Unresolved symbol: R1-rect
farther down in the fileMy intent is to be able to let the user write:
(ns sicm.example
(:require [sicmutils.calculus.manifold :refer [R2-rect]]))
(define-coordinates [x0 y0] R2-rect)
and not trigger warning: R2-rect already refers to #'sicmutils.env/R2-rect
; so this was my guess at how to do that, by checking what existed in the incoming state and reacting.
(you could argue that it IS a good warning and the user should absolutely not do a bare R2-rect
import then overwrite it, and I AGREE… except that to be compatible with all of the scheme code this is mirroring, the user gets an environment with everything exposed, then can rebind stuff selectively with define-coordinates
. The reason you’d do that is basically to give the coordinates names, like x y z
.)@borkdude another way to handle this would be
#_{:clj-kondo/ignore [:redefined-var]}
(define-coordinates [x0 y0] R2-rect)
but strangely that doesn’t seem to kill the warning.
it DOES if I paste in the macroexpansion directly:
#_{:clj-kondo/ignore [:redefined-var]}
(let* [G__43077
(sicmutils.calculus.manifold/with-coordinate-prototype R2-rect ['x0 'y0])]
(def R2-rect G__43077))
generate that inside the hook, you mean?
interesting, that almost works, and the reason why not is because I didn’t think of it 🙂
almost because now we get this:
#'sicmutils.env/R2-rect is referred but never used
from
(ns sicm.example
(:require [sicmutils.env:refer [R2-rect]]))
(define-coordinates [x0 y0] R2-rect)
got it, so generate all the declares, and also a vector of all of the syms
awesome, I’ll try that soon. thanks!
or you can generate something like potemkin import-vars which will then treat those defined vars as the imported vars with respect to arity, etc
I’m getting the hang of this. next @borkdude is to go document my hooks well and emit more custom warnings etc from the body
@borkdude is it the case that to make that work, I’d again be in the position of having to know which ones were being declared for the first time and which were overwriting?
is it possible to access other namespaces than hooks-api
in hooks? I think no; but for this particular task, I think I need unquote-node
and unquote-splicing-node
…
https://github.com/clj-kondo/clj-kondo/blob/d3c39e7f8023c571d102bc7adce483d040348351/parser/clj_kondo/impl/rewrite_clj/node/quote.clj#L59-L77
(let [seq-node? (some-fn api/list-node? api/vector-node?)
atom? (some-fn api/token-node? api/string-node? api/keyword-node?)
tree (tree-seq seq-node? :children node)]
(prn (remove (some-fn seq-node? atom?) tree)))
here is my “isolate via exclusion” method 🙂
potential bug…
(even? ('a {'a 10}))
triggers an “Insufficient input” error… I’m not sure why, and I am convinced this is correct (the call evaluates)Here is an example of a potential bug with :redundant-fn-wrapper
:
(map (fn [x]
{:pre [(odd? x)]}
(- x))
(range 10))
this triggers, but I would argue that it is NOT redundant because it adds a precondition. Thoughts?Also a bug. Ignore it with:
#_:clj-kondo/ignore
(fn [x]
{:pre [(odd? x)]}
(- x))
Thanks for finding these!@borkdude all 52k lines of tests + source from sicmutils linted, and all warnings and errors resolved! This project is amazing… I’m kicking myself for not enabling clj-kondo sooner. I’ll get an exact count when I polish the PR, but this process exposed a number of bugs that would have been damned hard to track down without the linter. Woohoo! Also I’m realizing that it’s such a pleasure to be able to write hooks that guide users toward correct usage of more difficult stuff like the pattern matching API. THANK YOU!