One of the challenges of coming to grips with `Query`'s on `Association`'s and `Dataset`s is inculcating an internal programming model of how they act and combine. This, in turn, depends critically on whether `Query` operators are *ascending* or *descending* either when acting alone or in concert as part of a function/query composition. Take the following example:
data = <|
"key" -> 1,
"keyA-Z" -> <|
"keyA" -> <|
"key1" -> A1,
"key2" -> A2,
"key3" -> A3|>,
"keyB" -> <|
"key1" -> B1,
"key2" -> B2,
"key3" -> B3|>
|>
|>;
Suppose we want to extract all elements at the `"key2"` level - here `{A2,B2}`. The query
Query["keyA-Z", All, "key2"]@data
(* <|"keyA" -> A2, "keyB" -> B2|> *)
does the job except for including the keys and while these can be readily peeled off ( `Query["keyA-Z", All, "key2"]@data//Values`), for "composability purposes" it's nice to be able maintain the operator form of the query by aiming to bring `Values` into the query itself. At first pass
Query["keyA-Z", All /* Values, "key2"]@data
(*
<|
"keyA" -> <|"key1" -> A1, "key2" -> A2, "key3" -> A3|>,
"keyB" -> <|"key1" -> B1, "key2" -> B2, "key3" -> B3|>
|>[[Values]][[All, "key2"]]
*)
seems appropriate noting from the [documentation](http://reference.wolfram.com/language/ref/Dataset.html):
> When one or more descending operators are composed with one or more
> ascending operators (e.g. `desc /* asc`), the descending part will be
> applied, then subsequent operators will be applied to deeper levels,
> and lastly the ascending part will be applied to the result.
e.g.
Query["keyA-Z", All /* f, "key2"]@data
(* f[<|"keyA" -> A2, "keyB" -> B2|>] *)
but as observed in its output the catch here is that `Values` is a *descending* operator (unlike the generic, *ascending* `f`). We can try turning it into an ascending one by wrapping it in a `Query` (subqueries tend to be ascending)
Query["keyA-Z", All /* Query[Values], "key2"]@data
(* <|"keyA" -> A2, "keyB" -> B2|>[[Values]] *)
but no beer. One way however, of turning `Values` into a generic, ascending function is by reverting to its pure form
Query["keyA-Z", All /* (Values@# &), "key2"]@data
(* {A2, B2} *)
While this works and provides an idiom for casting descending operators into ascending ones, (and also bringing post-processing within queries), it's also rather inelegant. In fact things seem to have come full circle; in [this question][1] the value of eschewing pure functions in favour of operator forms was compellingly made in several answers but here their re-introduction seems necessary as part of an operator's specification?
So can this "keyless `All`" `Query` be constructed in non-pure terms? - more broadly, is there a way of systematically specifying `Query` operators as either ascending or descending?
[1]: http://mathematica.stackexchange.com/questions/56504/v10s-operator-forms-what-are-they-good-for