Fork me on GitHub
#clojure-spec
<
2021-08-31
>
jumar10:08:54

Already asked in #cider but it looks unrelated, at least for one of my projects where it started to fail with lein repl (maybe a dependency update but I believed it worked fine and don't remember any changes in dependencies).

Caused by: Syntax error macroexpanding clojure.core/defn at (clojure/spec/alpha.clj:85:1).
	at clojure.lang.Compiler.checkSpecs(Compiler.java:6972)
	at clojure.lang.Compiler.macroexpand1(Compiler.java:6988)
	at clojure.lang.Compiler.macroexpand(Compiler.java:7075)
...
	at clojure.main$loading__6721__auto____8974.invoke(main.clj:11)
	at clojure.main__init.load(Unknown Source)
	at clojure.main__init.<clinit>(Unknown Source)
	... 55 more
Caused by: java.lang.Exception: #object[clojure.spec.alpha$and_spec_impl$reify__1057 0x459f703f "clojure.spec.alpha$and_spec_impl$reify__1057@459f703f"] is not a fn, expected predicate fn
What could be a reason for this ? We use these if it matters:
[expound "0.8.9"]
                                             [orchestra "2021.01.01-1"]

Alex Miller (Clojure team)12:08:58

Sorry, not sure what that is

Alex Miller (Clojure team)12:08:36

Can you make something reproducible to share?

jumar12:08:10

I'll try to check if it isn't something specific to the dependencies / toolchain (which is likely)

MatthewLisp19:08:21

Hello 👋 I'm defining a spec using https://clojure.org/guides/spec#_collections, and i quote:

Tuple - (s/tuple double? double? double?)
Designed for fixed size with known positional "fields"
Conforms to a vector of the values
What if, i have a fixed size collection but with unknown positional "fields", and the collection is NOT homogenous ?

flowthing19:08:00

cat might work, if I understood correctly?

user=> (require '[clojure.spec.alpha :as spec])
nil
user=> (spec/def ::elements (spec/cat :int int? :string string?))
:user/elements
user=> (spec/valid? ::elements [1 "a" :b])
false
user=> (spec/valid? ::elements [1])
false
user=> (spec/valid? ::elements [1 "a"])
true

MatthewLisp19:08:53

what about ["a" 1] ?

MatthewLisp19:08:08

That's what i meant with unknown positional fields

flowthing19:08:57

Yeah, this is basically what Alex said, but:

user=> (spec/def ::element
         (spec/or :int int? :string string? :keyword keyword?))
:user/element
user=> (spec/def ::elements (spec/coll-of ::element :count 3))
:user/elements
user=> (spec/valid? ::elements [1 "a" :b])
true
user=> (spec/valid? ::elements [1])
false
user=> (spec/valid? ::elements [1 "a"])
false

Alex Miller (Clojure team)19:08:41

what are you expecting to validate about this collection?

Alex Miller (Clojure team)19:08:11

(s/coll-of any? :count 2)

MatthewLisp20:08:42

Not just the size, an example of the collection:

[{:identity "username"
  :value     "john"}

 {:identity "age"
  :value     "30"}]
One might think this can be described with s/coll because it appears to be an homogenous collection, however, depending on the context of the application, i have different values on this collection... The way i'm defining the two entries of the collection is as follows:
;; username

(s/def :username/identity
  #{"username"})

(s/def :username/value
  "PREDICATE_HERE")

(s/def :entry/username
  (s/keys :req-un [:username/identity
                   :username/value]))

;; age

(s/def :age/identity
  #{"age"})

(s/def :age/value
  "PREDICATE_HERE")

(s/def :entry/age
  (s/keys :req-un [:age/identity
                   :age/value]))

;; now i'm trying to define the collection using :entry/username and :entry/age

MatthewLisp20:08:12

i've over simplified the keywords names because i'm obfuscating the real names

MatthewLisp20:08:23

but the structure is this

Alex Miller (Clojure team)20:08:51

(s/coll-of (s/or :user :entry/username :age :entry/age) :count 2)

Alex Miller (Clojure team)20:08:41

there are more options for the content, like wrapping that in s/nonconforming to avoid the s/or tag, or use s/multi-spec instead for open extension there, etc

MatthewLisp20:08:36

This approach leads me with a collection having two entries of for example :entry/username as being valid I'm starting to think something using multi-spec, might work!

MatthewLisp20:08:44

Will look into s/nonconforming docs also

Alex Miller (Clojure team)20:08:03

the last is un-doc'ed but it basically conforms, then returns the original value