Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

No generic collection type? #384

Open
weissjeffm opened this issue Mar 21, 2017 · 6 comments
Open

No generic collection type? #384

weissjeffm opened this issue Mar 21, 2017 · 6 comments

Comments

@weissjeffm
Copy link

How can I define a collection spec that works on all collections (not just vectors or sets)?

To illustrate the issue I'm having:

cljs.user> (s/validate [s/Int] #{1 2})
#error {:message "Value does not match schema: (not (sequential? #{1 2}))", :data {:type :schema.core/error, :schema [#schema.core.Predicate{:p? #object[cljs$core$integer_QMARK_ "function cljs$core$integer_QMARK_(n){
return (typeof n === 'number') && (!(isNaN(n))) && (!((n === Infinity))) && ((parseFloat(n) === parseInt(n,(10))));
}"], :pred-name cljs$core$integer?}], :value #{1 2}, :error (not (sequential? #{1 2}))}}
	
cljs.user> (s/validate #{s/Int} [1 2])
#error {:message "Value does not match schema: (not (set? [1 2]))", :data {:type :schema.core/error, :schema #{#schema.core.Predicate{:p? #object[cljs$core$integer_QMARK_ "function cljs$core$integer_QMARK_(n){
return (typeof n === 'number') && (!(isNaN(n))) && (!((n === Infinity))) && ((parseFloat(n) === parseInt(n,(10))));
}"], :pred-name cljs$core$integer?}}, :value [1 2], :error (not (set? [1 2]))}}

It seems like one of these should work, or if they don't, there should be a third option where the schema is "I don't care what type of collection it is, as long as each item in it is an Int".

I can get what I want, sort of, with a little function I define myself, but seems like there ought to be a better way:

cljs.user> (defn coll [schema] (s/cond-pre [schema] #{schema}))
#'cljs.user/coll
cljs.user> (s/validate (coll s/Int) [1 2])
[1 2]
cljs.user> (s/validate (coll s/Int) #{1 2})
#{1 2}
@w01fe
Copy link
Member

w01fe commented Mar 21, 2017

You are the second person to ever ask about this -- here is the first:

https://groups.google.com/forum/#!searchin/prismatic-plumbing/seqable%7Csort:relevance/prismatic-plumbing/XI6_slJh3sc/rna2jD0fAAAJ

I would still say the same thing: I can see the utility, but myself have never needed it (since usually I care whether the collection is sequential or not). We'd be open to a PR that adds this, but I would like to hear a bit about your use case first if you don't mind sharing.

@weissjeffm
Copy link
Author

I believe you when you say you never needed it and only one person ever asked. Still, I'm surprised. The "collection" concept is all over clojure, tons of core functions accept collections as arguments. So any function that calls map or filter or any of those other collection functions, would potentially need the schema concept I'm asking for.

This particular use case is a clojurescript reagent component that is making a pretty HTML table. It doesn't really care about the collection type, if the caller wants no duplicates he can coerce to a set himself. If the caller has already sorted the contents, he can pass in a sequence. So neither a set nor a sequence seems to be the correct schema here. I don't think it's correct to force the argument to a sequence, that puts a burden on the caller for no other purpose than satisfying schema.

@w01fe
Copy link
Member

w01fe commented Mar 21, 2017

OK, that makes sense -- thanks for the info.

I guess there's also some concern about making coercion work properly -- I'm not sure if empty and into will work, i think sometimes it may reverse the sequence or something (with e.g. list) or fail (e.g. records). I.e. the problem is that seq isn't easily reversible I think. If it can't be done without rough edges then i'd probably rather leave it out rather than have it bite someone, but if it can then more than happy to accept a PR.

@aiba
Copy link
Contributor

aiba commented Jun 14, 2019

FWIW, my team would find it useful to have a schema type that allows either [Foo] or #{Foo}.

We have a bunch of functions that need to take a collection of items of a given type, where order doesn't matter. Some callers have those items in a set and some have them in vectors.

@cloojure
Copy link
Contributor

cloojure commented Jun 30, 2019 via email

@frenchy64
Copy link
Contributor

Another use-case: the result of clojure.core/iteration returns a Seqable + Reducible, which doesn't work with the [] schema.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

5 participants