Strange behaviour of the alternative operator //

73 Views Asked by At

Using JQ 1.5 I've problems understanding the output of the alternative operator // in a specific situation.

Given this input:

{
    "a": 42,
    "b": false,
    "c": null
}

I expected the expression (.a, .b, .c, .d) // -1 to return this:

42
-1
-1
-1

But in fact it returns this instead:

42

If I replace // with another operator like < then I indeed get four results instead of just one (the actual results are not important here, just their number):

> jq '(.a, .b, .c, .d) < -1' input.json
false
true
true
true

Note: The expression (.a, .b, .c, .d) | . // -1 returns the expected output. This is not the question. I'd like to know why the initial expression does not work.

2

There are 2 best solutions below

2
peak On BEST ANSWER

The 1.5 documentation is, to put it bluntly, just wrong.

The jq FAQ provides this succinct and useful summary:

"A // B" either produces the truthy elements of A if there are any,
or else the entire stream B.
0
A.H. On

Exactly after posting my question I stumbled over the exact answer in the manual of the developer version. :shrug:

So far the manual page for jq 1.5 says about //:

A filter of the form a // b produces the same results as a, if a produces results other than false and null. Otherwise, a // b produces the same results as b.

The developer version says additionally:

[...]Note: some_generator // defaults_here is not the same as some_generator | . // defaults_here. The latter will produce default values for all non-false, non-null values of the left-hand side, while the former will not. [...] In (false, null, 1) | . // 42 the left-hand side of // is ., which always produces just one value, while in (false, null, 1) // 42 the left-hand side is a generator of three values, and since it produces a value other false and null, the default 42 is not produced.