'Jq label and break to break out of control structure

I'm trying to learn jq label and break.

Here's my attempt: https://jqplay.org/s/YHxn1dRlQO

Filter:
label $out | reduce .[] as $item (0; if $item==1 then break $out else .+$item end)

Input:
[3,2,1]

Output:
empty

I was expecting output 5.

I don't really know how label and break works.

Can you explain how to correctly use them with examples?



Solution 1:[1]

Given your input array, .==1 will never evaluate to true. $item==3, $item==2 and $item==1, as well as .==0, .==3 and .==5, however, would.

And if it does, it still wouldn't output 5 because break is treated like an error that was caught.

From the manual:

The break $label_name expression will cause the program to to act as though the nearest (to the left) label $label_name produced empty.

Therefore

label $out | reduce .[] as $item (0;
  if $item==1 then break $out else .+$item end
)

will correctly produce empty.

You can still capture empty though, for instance

label $out | reduce .[] as $item (0;
  if $item == 1 then break $out else . + $item end
)? // (.[:index(1)] | add)
5

Demo

Solution 2:[2]

break does not work (in the way one might reasonably expect (*) ) with reduce. Whether that is by design or not, I cannot say, but perhaps it's not surprising as reduce is intended for reductions.

Apart from reduce, though, break behaves properly elsewhere, notably with foreach.


(*) Consider for example:

  label $out
  | reduce range(0;10) as $i (0; .+$i | if $i == 4 then ., break $out else . end)

One might reasonably expect the accumulated sum (0+1+2+3+4) to be emitted, but instead the result is empty.

By contrast, if you replace reduce with foreach, the result is as expected:

0
1
3
6
10

Notice that to achieve the effect that is presumably wanted with reduce, one can simply use last in conjunction with foreach:

  last(label $out
       | foreach range(0;10) as $i (0; .+$i | if $i == 4 then ., break $out else . end))

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1
Solution 2