Fork me on GitHub

What is the reason spec chose a custom deftype LazyVar over the built-in delay in its implementation?


I'm trying to come up with something that would work in Clojure for this case:

(def input (LazyVar. (fn [] (line-seq ( ( "1\n2\n3\n")))) nil))
such that you don't have to write @input but just input so the first time it's derefed by Clojure it starts its realization. Just a naked line-seq doesn't work, since that starts reading once it's def-ed.


@alexmiller in the gen namespace


I think in Clojure I would have to write a subclass of clojure.lang.Var to make that work.

Alex Miller (Clojure team)16:11:33

sorry, I don't actually see what you're talking about


And maybe I should just go with @input and not do any magic... This lead to the question: why is gen/LazyVar not just a delay but a custom data structure. Ah right.. sorry, the LazyVar is something in CLJS, not CLJ. facepalm


I'll ask over there in #clojurescript


I am confused about the syntax for (or) and (and) in s/keys. My understanding of it was that anything that is passed to or could be correct, and anything that passed into and has to be present. Did I misunderstand? My intuition does not work for the following example:

(s/def :foo/foo #{:foo})
(s/def :bar/foo #{:bar})
(s/def ::an-int int?)

(s/def ::baz (s/keys :req-un [(or :foo/foo
                                  (and :bar/foo

(s/valid? ::baz {:foo :foo})
;; => false
(s/valid? ::baz {:foo :bar})
;; => true


ok it looks like when you have the same naked keyword (not sure of the right terminology, keyword without the NS) then it will always take the last one defined. That's a huge bummer, since I wanted to be able to spec something like "In this case, do this, in this other case, do this + another piece of data", and the way that was being specced before was by storing everything as a tuple


@socksy can't you use s/or for either case?


more verbose


@socksy You'll need to wrap s/keys with s/and and add your rules via a predicate -- or use s/or around s/keys as @borkdude suggests.


yes I think it might be possible. I'll go hit my head on it


i am thinking my own predicate will probably be the most readable but let's see


maybe spec2 has a better answer to this... although I'm not sure if s/select can solve this case


Another option would be a multi-spec I think?


(s/def ::baz (s/or :foo-case (s/keys :req-un [:foo/foo])
                   :bar-case (s/keys :req-un [:bar/foo ::an-int])))
is not too bad actually

👍 3

Now I wonder how you would use this in spec2. I think you would define ::baz as the thing with all possible keys and then use s/select for either case?


(s/def ::baz (s/schema [:foo/foo :bar/foo ::an-int]))
(s/def ::foo-case (s/select [:foo/foo]))
(s/def ::boo-case (s/select [:bar/foo ::an-int]))
Something like this?

🤷 3