On Thursday, 13 June 2013 19:50:32 UTC+1, Brandon Bloom wrote:
> Haven't decades of experience in software taught us that failing fast on invalid / unexpected input is a good idea?
You're operating on the assumption that a vector is an invalid or unexpected input for the keys function, which I am arguing, it is not.
> I guess I'm just a little suspicious of core functions that try to be too "clever" and support lots of different input types in marginally inconsistent ways
I think that this is neither clever nor inconsistent.
The problem is: if you try and treat maps and vectors as part of the same abstraction, you'll ultimately run into inconsistencies because they already have very different defined behaviours.
For example, consider that one is considered as a sequence of key/value pairs and the other isn't: I already highlighted the difference between (seq {0 :a 1 :b}) and (seq [:a :b]) - If you expect 'keys' to behave like '(partial map first)', then it is clearly inconsistent when applied to vectors.
Then there are also functions like 'dissoc' which fail if you try to remove a key/value mapping from a vector.
No matter how you break it down, if you attempt to unify maps and vectors and other vaguely associative types under the same abstraction then there will be circumstances where the inconsistencies show through. The most likely outcome is that you don't actually end up with a consistent abstraction, i.e. each function will operate on a slightly different subset of types. This could work, but it would also be very tricky to reason about. Contrast with the sequence abstraction, which I think is much more clean and consistent: functions that operate on a sequence tend to work for any sequence type.
Anyway, none of this is a particularly big deal. Clearly 'keys' is a function which could be defined to work on vectors in a reasonably sane way. I'd still personally prefer an exception. But mostly, I'm just pointing out that maps and vectors are quite different beasts, and trying to urge caution when it comes to stretching an abstraction over disparate types..