Apply TCO to recurse/1, add recurse/2; tweak docs
Signed-off-by: Nicolas Williams <nico@cryptonector.com>
This commit is contained in:
1 parent
a2f99d43c3
commit
f8fed0f0bc
2 files changed
+35
-7
No files matched your search
@@ -928,9 +928,13 @@ static const char* const jq_builtins[] = {
|
|||||||
"def del(f): delpaths([path(f)]);",
|
"def del(f): delpaths([path(f)]);",
|
||||||
"def _assign(paths; value): value as $v | reduce path(paths) as $p (.; setpath($p; $v));",
|
"def _assign(paths; value): value as $v | reduce path(paths) as $p (.; setpath($p; $v));",
|
||||||
"def _modify(paths; update): reduce path(paths) as $p (.; setpath($p; getpath($p) | update));",
|
"def _modify(paths; update): reduce path(paths) as $p (.; setpath($p; getpath($p) | update));",
|
||||||
"def recurse(f): ., (f | select(. != null) | recurse(f));",
|
|
||||||
|
// recurse
|
||||||
|
"def recurse(f): def r: ., (f | select(. != null) | r); r;",
|
||||||
|
"def recurse(f; cond): def r: ., (f | select(cond) | r); r;",
|
||||||
"def recurse: recurse(.[]?);",
|
"def recurse: recurse(.[]?);",
|
||||||
"def recurse_down: recurse;",
|
"def recurse_down: recurse;",
|
||||||
|
|
||||||
"def to_entries: [keys[] as $k | {key: $k, value: .[$k]}];",
|
"def to_entries: [keys[] as $k | {key: $k, value: .[$k]}];",
|
||||||
"def from_entries: map({(.key): .value}) | add | .//={};",
|
"def from_entries: map({(.key): .value}) | add | .//={};",
|
||||||
"def with_entries(f): to_entries | map(f) | from_entries;",
|
"def with_entries(f): to_entries | map(f) | from_entries;",
|
||||||
|
|||||||
@@ -22,7 +22,7 @@ body: |
|
|||||||
combine two filters, like addition, generally feed the same input to
|
combine two filters, like addition, generally feed the same input to
|
||||||
both and combine the results. So, you can implement an averaging
|
both and combine the results. So, you can implement an averaging
|
||||||
filter as `add / length` - feeding the input array both to the `add`
|
filter as `add / length` - feeding the input array both to the `add`
|
||||||
filter and the `length` filter and dividing the results.
|
filter and the `length` filter and then performing the division.
|
||||||
|
|
||||||
But that's getting ahead of ourselves. :) Let's start with something
|
But that's getting ahead of ourselves. :) Let's start with something
|
||||||
simpler:
|
simpler:
|
||||||
@@ -40,14 +40,16 @@ manpage_intro: |
|
|||||||
running the command `jq 'map(.price) | add'` will take an array of
|
running the command `jq 'map(.price) | add'` will take an array of
|
||||||
JSON objects as input and return the sum of their "price" fields.
|
JSON objects as input and return the sum of their "price" fields.
|
||||||
|
|
||||||
By default, `jq` reads a stream of JSON objects (whitespace
|
`jq` can accept text input as well, but by default, `jq` reads a
|
||||||
separated) from `stdin`. One or more <files> may be specified, in
|
stream of JSON entities (including numbers and other literals) from
|
||||||
|
`stdin`. Whitespace is only needed to separate entities such as 1
|
||||||
|
and 2, and true and false. One or more <files> may be specified, in
|
||||||
which case `jq` will read input from those instead.
|
which case `jq` will read input from those instead.
|
||||||
|
|
||||||
The <options> are described in the [INVOKING JQ] section, they
|
The <options> are described in the [INVOKING JQ] section; they
|
||||||
mostly concern input and output formatting. The <filter> is written
|
mostly concern input and output formatting. The <filter> is written
|
||||||
in the jq language and specifies how to transform the input
|
in the jq language and specifies how to transform the input
|
||||||
document.
|
file or document.
|
||||||
|
|
||||||
## FILTERS
|
## FILTERS
|
||||||
|
|
||||||
@@ -1250,7 +1252,7 @@ sections:
|
|||||||
output: ['[1,2,4,8,16,32,64]']
|
output: ['[1,2,4,8,16,32,64]']
|
||||||
|
|
||||||
|
|
||||||
- title: "`recurse(f)`, `recurse`, `recurse_down`"
|
- title: "`recurse(f)`, `recurse`, `recurse(f; condition), `recurse_down`"
|
||||||
body: |
|
body: |
|
||||||
|
|
||||||
The `recurse(f)` function allows you to search through a
|
The `recurse(f)` function allows you to search through a
|
||||||
@@ -1275,10 +1277,24 @@ sections:
|
|||||||
When called without an argument, `recurse` is equivalent to
|
When called without an argument, `recurse` is equivalent to
|
||||||
`recurse(.[]?)`.
|
`recurse(.[]?)`.
|
||||||
|
|
||||||
|
`recurse(f) is identical to `recurse(f; . != null)` and can be
|
||||||
|
used without concerns about recursion depth.
|
||||||
|
|
||||||
|
`recurse(f; condition)` is a generator which begins by
|
||||||
|
emitting . and then emits in turn .|f, .|f|f, .|f|f|f, ... so long
|
||||||
|
as the computed value satisfies the condition. For example,
|
||||||
|
to generate all the integers, at least in principle, one
|
||||||
|
could write `recurse(.+1; true)`.
|
||||||
|
|
||||||
For legacy reasons, `recurse_down` exists as an alias to
|
For legacy reasons, `recurse_down` exists as an alias to
|
||||||
calling `recurse` without arguments. This alias is considered
|
calling `recurse` without arguments. This alias is considered
|
||||||
*deprecated* and will be removed in the next major release.
|
*deprecated* and will be removed in the next major release.
|
||||||
|
|
||||||
|
These `recurse` filters are all written to take advantage of
|
||||||
|
jq's optimizations of certain cases of tail recursion. In
|
||||||
|
particular, there is no memory overhead due to the
|
||||||
|
recursion.
|
||||||
|
|
||||||
examples:
|
examples:
|
||||||
- program: 'recurse(.foo[])'
|
- program: 'recurse(.foo[])'
|
||||||
input: '{"foo":[{"foo": []}, {"foo":[{"foo":[]}]}]}'
|
input: '{"foo":[{"foo": []}, {"foo":[{"foo":[]}]}]}'
|
||||||
@@ -1287,6 +1303,7 @@ sections:
|
|||||||
- '{"foo":[]}'
|
- '{"foo":[]}'
|
||||||
- '{"foo":[{"foo":[]}]}'
|
- '{"foo":[{"foo":[]}]}'
|
||||||
- '{"foo":[]}'
|
- '{"foo":[]}'
|
||||||
|
|
||||||
- program: 'recurse'
|
- program: 'recurse'
|
||||||
input: '{"a":0,"b":[1]}'
|
input: '{"a":0,"b":[1]}'
|
||||||
output:
|
output:
|
||||||
@@ -1294,6 +1311,13 @@ sections:
|
|||||||
- '[1]'
|
- '[1]'
|
||||||
- '1'
|
- '1'
|
||||||
|
|
||||||
|
- program: 'recurse(. * .; . < 20)'
|
||||||
|
input: 2
|
||||||
|
output:
|
||||||
|
- 2
|
||||||
|
- 4
|
||||||
|
- 16
|
||||||
|
|
||||||
- title: "`..`"
|
- title: "`..`"
|
||||||
body: |
|
body: |
|
||||||
|
|
||||||
|
|||||||
Reference in new issue
Block a user