Any reason only a map implements IFn with an extra not found value?
user=> ({:a 1} :b :b)
:b
user=> (#{:a :b :c} :d :d)
Execution error (ArityException) at user/eval29 (REPL:1).
Wrong number of args (2) passed to: clojure.lang.PersistentHashSet
user=> ([] 0 :d)
Execution error (ArityException) at user/eval31 (REPL:1).
Wrong number of args (2) passed to: clojure.lang.PersistentVector
Not really a problem, just something I wondered about when implementing invalid arity linting for collections
The set ifn is contains right? Feels weird for that to have a not found notion. And vectors throw index out of bounds exceptions. To me it’s only a map that may or may not have a value associated with something, right?
but now i’m reading nth docstring
it's not contains? for set:
user=> (#{:foo :bar} :foo)
:foo
You convinced me on the vector, less so on the set.
this would be a good use case for set:
(#{:foo nil} nil :not-found)I agree you can do this in 10 different other ways in clojure, it just feels inconsistent to treat maps and sets differently. sets are basically maps that map keys onto themselves
The thing I'm trying to catch in clj-kondo is this:
(map {:a :b} [1 2 3] [1 2 3])
but this was actually valid, which I didn't know from intuition. Then I tested it for other collections.go is infuriating to me because that’s actually canonically how they do sets. maps with an empty struct as a value. But i always consider that one implementation detail of sets, not necessarily an abstract definition of them. That example does look strange but makes sense.
$ clj -M:clj-kondo/dev --lint - <<< "(map {:a :b} [1 2 3] [1 2 3] [1 2 3])"
<stdin>:1:6: error: a map is called with 3 args but expects 1 or 2
linting took 29ms, errors: 1, warnings: 0I don't think it's just an implementation detail, it's a mathematical notion too
i’m cracking up because the name of the set is impl
but you certainly don’t “assoc set value true”. you “add” an element to a set. You can model it as a map associating that value to some sentinel value. I think javascript does this for arrays as well. But it’s an implementation detail to me.
({:a 1} :a) ;; get element a from map
(#{:a} :a) ;; get element from set
({:a 1} :a :not-found) ;; get element a from map, :not-found if not found
(#{:a} :a :not-found) ;; get element from set, :not-found if not found.
this isn't weird or far-fetched to me at allI'm not talking about assoc, just get
The set operation for invoke is get: https://github.com/clojure/clojure/blob/6a4ba6aedc8575768b2fff6d9c9c7e6503a0a93a/src/jvm/clojure/lang/APersistentSet.java#L53
this is worth an Ask, i think
lol:
cljs.user=> (#{:a :b :c} :d :not-found)
:not-foundand i'd be willing to write a patch lol
yeah, sure, before Ask-ing, might be good to have a response. Oh, I'm willing to write a patch too, that's the most fun part and the least amount of work.
it truly is
https://ask.clojure.org/index.php/14815/not-found-arg-for-invoking-set-and-vector
(lol, squint also supports it already, just because it treats it as a get call: https://squint-cljs.github.io/squint/?src=gzip%3AH4sIAAAAAAAAE9NQrrZKVLBKUrBKrlWwSlGwyssv0U3LL81L0QQA4r4UOxsAAAA%3D)