Fork me on GitHub
#clj-kondo
<
2022-09-03
>
Jacob Emcken06:09:15

I am getting a expected symbol from clj-kondo for Clojure spec used with test.check (example below). I can't figure out if I am doing it wrong or if I found a sharp edge of clj-kondo.

Jacob Emcken07:09:03

This works fine:

(spec/def ::a-fn fn?)

(spec/def ::name string?)

(spec/def ::hey
  (spec/keys :req [::a-fn ::name]))

(spec/valid? ::hey {::a-fn identity ::name "Hello"}) => true

borkdude07:09:33

Can you post the example with the warning?

Jacob Emcken07:09:03

Now I want to generate test data, for no particular reason other than "I can" (or should be able to) with (gen/generate (spec/gen ::hey)) But it gives me:

; Execution error (ExceptionInfo) at user/eval9271 (form-init5066133147658145143.clj:81).
; Unable to construct gen at: [:user/a-fn] for: :user/a-fn

Jacob Emcken07:09:29

Then I add:

(spec/fdef ::a-fn
    :args (spec/cat)
    :ret int?)

Jacob Emcken07:09:39

Which makes test.check happy... now I can generate test data. But now clj-kondo complains about expected symbol:

(spec/fdef ::a-fn
           ^^^^^^

borkdude07:09:06

What if you make that a symbol? I didn't know function specs could be made with keywords or if it's maybe accidentally supported

borkdude07:09:50

A quoted symbol

Jacob Emcken07:09:05

I don't understand how. If I use anything but ::a-fn then how does spec know what I am defining?

lassemaatta07:09:38

Perhaps you should use fspec instead of fdef? :thinking_face:

borkdude07:09:12

FWIW, the docs for fdef say: > Takes a symbol naming a function

👍 1
Jacob Emcken07:09:35

I'll look into fspec

borkdude07:09:52

but I think it may accidentally work for a keyword. So if you try: my-namespace.a-fn it will work per the docstring

Jacob Emcken08:09:22

I could not figure out how to make spec, like my quoted symbol, but the following seems to work:

(spec/def ::a-fn
  (spec/fspec :args (spec/cat)
              :ret nil?))
;; ^^^^^^^^^^^^^^^^^^^^^^^^^^^
;; NOTICE THIS 

(spec/def ::name string?)

(spec/def ::hey
  (spec/keys :req [::a-fn ::name]))

(spec/valid? ::hey {::a-fn println ::name "Hello"})
(spec/explain ::hey {::a-fn println ::name "Hello"})

(gen/generate (spec/gen ::hey))

borkdude08:09:31

Yeah sorry it should be just an unquoted symbol but good that you figured it out

slipset10:09:12

This is probably a RTFM, but still: I’ve written a macro like

(defmacro with-foo [foo & body] 
   `(let [~foo ...]
      ~@body))
to be used as:
(with-foo lol
   (println lol)
What kind of lint-as magic do I need to invoke to let clj-kondo understand that lol is in fact defined in the call to println?

borkdude10:09:20

@slipset There is a built-in macro similar to this: cljs.test/async

slipset10:09:12

Lovely! Thanks!