The following works in Clojure:
(keys (filter (comp odd? val) {:a 1 :b 2 :c 3}))
The docstrings for keys
and vals
don't indicate that you can do this. Is this accidential or intentional?
I vaguely recall Alex Miller indicating at some point that this capability was deemed useful and is intentionally allowed. Yes, this is an appeal to authority, but nevertheless, it makes a fairly convincing argument.
There was evidently an attempt to
disallow this, which was reverted
because it evidently breaks subseq
.
There are unit tests that specifically check that you can pass various empty seqables to keys
and vals
and get back
nil
(thus arguing, indirectly via the presence unit tests, that it is intentional that these functions can accept things
other than maps—perhaps so long as they are empty seqables.)
There is a comment in CLJ-1602 that touches specifically on the fact that sequences of map entries are passed to these functions
There are a few places that rely on passing a seq of Map.Entry to keys/vals (not just a map instance)...
and the relevant patch specifically takes care not to break code that relies on this behavior.
While the above isn't evidence that the capability is truly intentional and supported, this appears to be the strongest evidence that there is at least a circumspect intent not to break existing usage.
There is a Clojuredocs example specifically illustrating this use case. This is of course not evidence that such programs are valid; it only illustrates that it is a known capability.
In summary, my hunch is that it wasn't intentional, but was discovered to be useful, and is now in a place where you can rely on it working even though it isn't formally documented. Your ability to use it safely depends on the combination of Hyrum's Law at work, and the Clojure team's conservative stance, leaning towards never breaking things if at all possible.
Update: See
https://ask.clojure.org/index.php/9838/is-it-legal-to-apply-keys-vals-to-a-sequence-of-map-entries
and
https://clojure.atlassian.net/browse/CLJ-2592