gen_op_var_bound(LOADV, array_var));
}
+block gen_fold(const char* varname, block init, block fold) {
+ block loop = BLOCK(fold, gen_op_var_unbound(STOREV, varname), gen_op_simple(BACKTRACK));
+ return BLOCK(gen_op_simple(DUP),
+ init,
+ block_bind(gen_op_var_unbound(STOREV, varname),
+ BLOCK(gen_op_target(FORK, loop),
+ loop,
+ gen_op_var_unbound(LOADV, varname)),
+ OP_HAS_VARIABLE));
+}
+
block gen_assign(block expr) {
block result_var = block_bind(gen_op_var_unbound(STOREV, "result"),
gen_noop(), OP_HAS_VARIABLE);
block gen_subexp(block a);
block gen_both(block a, block b);
block gen_collect(block expr);
+block gen_fold(const char* varname, block init, block body);
block gen_assign(block expr);
block gen_definedor(block a, block b);
block gen_condbranch(block iftrue, block iffalse);
input: '{}'
output: [42]
- - title: Variables and Functions
+ - title: Advanced features
body: |
Variables are an absolute necessity in most programming languages, but
they're relegated to an "advanced feature" in jq.
(many jq functions such as `map` and `find` are in fact written
in jq).
+ Finally, jq has a `fold` operation, which is very powerful but a
+ bit tricky. Again, it's mostly used internally, to define some
+ useful bits of jq's standard library.
+
entries:
- title: Variables
body: |
- program: 'def addvalue(f): f as $x | map(. + $x); addvalue(.[0])'
input: '[[1,2],[10,20]]'
output: ['[[1,2,1,2], [10,20,1,2]]']
+
+ - title: Fold
+ body: |
+
+ The `fold` syntax in jq allows you to combine all of the
+ results of an expression by accumulating them into a single
+ answer. As an example, we'll pass `[3,2,1]` to this expression:
+
+ fold 0 as $sum (.[] | $sum + .)
+
+ The variable `$sum` is first given the value `0`. The body
+ of the fold (i.e. `.[] | $sum + .`) is evaluated. `.[]`
+ produces three results, `3`, `2`, and `1`. For the first
+ one, `$sum + .` gives `3`.
+
+ Having produced this answer, jq backtracks to find the next
+ result as per usual. However, this time, `$sum` is set to
+ the previous value of the body, so `$sum + .` gives
+ `5`. After the final backtracking, `$sum + .` gives
+ `6`. This final value is used as the value of the entire
+ `fold` expression, so the above filter returns `6`.
+
+ More formally, in order to evaluate `fold INIT as $VAR
+ (BODY)`, jq first sets `$VAR` to the value of `INIT`. It
+ then runs through `BODY`. Each time `BODY` produces a value,
+ `$VAR` is set to that value and jq backtracks to find the
+ next one. When `BODY` stops producing values, the final
+ value of `$VAR` is the result of the entire expression.
+
+ examples:
+ - program: 'fold 0 as $sum (.[] | $sum + .)'
+ input: '[10,2,5,3]'
+ output: ['20']
- title: Assignment