stedolan/jq — pull request #428 by slapresta (2014-06-18 00:39:10+00:00)
Title: Drop the `select` from the filtering builtins

**As it stands, this is a backwards-incompatible change. Handle with care.**
*(Also, at this moment, this is more of a proposal and lacks documentation)*

So, I believe dropping `select` from `arrays`, `objects`, `numbers`, ... would improve jq's standard library. This is, we would substitute `def arrays: select(type == "array");` with `def arrays: type == "array";`

> But `select(numbers)` takes longer to write than `numbers`! Why would we ever want that?

**Composability**

Right now, if you want to select all numbers from your input, `map(numbers)` is great. But what happens if you want to select everything but numbers? `map(strings, booleans, arrays, objects)` does not roll off the tongue so easily, and it is pretty easy to miss the fact that I forgot to include `nulls`. And, if jq ever needs to add another type *(unlikely, yet stranger things have happened)* my script will break.

Composability empowers the user to build better things out of reusable parts: map(select(not numbers)) is pretty readable and self-evident. Defining `filter(f)` as `map(select(f))` would make it even more.

**Expressiveness**

Since these builtins are simpler and more reusable, they allow for more expressive constructs. For example, defining `any(f)` as `map(f) | any` allows us to check if an array contains any booleans by writing `any(booleans)`. Isn't that great?

Similarly, `iterables`, `values` and `scalars` could be defined in terms of their single-type companions: `def iterables: arrays or objects;`. Isn't that great? Rest assured, it would carry none of the performance concerns mentioned at #427.

> Okay, you convinced me *(did I?)*. How do we implement this?

Well, there are some things that are backwards-compatible, such as `any(f)` and `filter(f)`, and can be back-ported effortlessly. The bulk of this change is dropping the `select(...)` on the type builtins.

We can either wait until a major version comes to make the switch (breaking backwards compatibility on minor versions is evil) or we can add them as `is_number`, `is_string`, `is_iterable`, and so on. This is inconvenient for two reasons:

1) We need to solve The Underscore Dilemma(TM) first (`to_entries`, `leaf_paths`; `tonumber`, `tostring`)
2) It's uglier.

So, well, here it is. Does it make sense to you? Discuss, and thanks for reading.