]> granicus.if.org Git - jq/commitdiff
Make |= delete LHS when RHS is empty (Fix #1314)
authorNicolas Williams <nico@cryptonector.com>
Fri, 27 Jan 2017 23:46:00 +0000 (17:46 -0600)
committerNicolas Williams <nico@cryptonector.com>
Mon, 30 Jan 2017 20:11:05 +0000 (14:11 -0600)
Now that #1313 is fixed, |= no longer outputs null when the RHS update
expression outputs empty.

When a user wants to keep the current value of the LHS they would have
the RHS update expression output `.`, so having `empty` achieve the same
thing would be redundant.  The obvious thing to do is to delete the LHS
when the RHS update outputs `empty` (i.e., doesn't output any values).

It's reasonable to think that existing programs won't be broken by this
change, because reduce and |= not handling empty well is clearly a bug.
(Though it's possible that some programs were using empty to quickly
terminate reduce or |=, it's not likely.  They should use label/break
instead.)

Prior to this change |= would use the _last_ value output by the RHS
update expression.  With this change |= will use the _first_ value
instead.  This change _is_ a minor backwards-incompatible change.  It
may or may not be acceptable; we'll see.  It is a useful change in that
it makes |= faster when the update expression produces multiple values.

docs/content/3.manual/manual.yml
jq.1.prebuilt
src/builtin.jq

index ae7a9d39e1f72ab086e0160f9241b092a2180627..8eb1a0c42a7b1e750fbb0444e87fcd920780f616 100644 (file)
@@ -2818,8 +2818,12 @@ sections:
           not a valid or useful path expression in `.`); use `$var |
           .foo |= . + 1` instead.
 
-          If the right-hand side outputs multiple values, only the last
-          one will be used.
+          If the right-hand side outputs no values (i.e., `empty`), then
+          the left-hand side path will be deleted, as with `del(path)`.
+
+          If the right-hand side outputs multiple values, only the first
+          one will be used (NOTE: it used to be that only the last one was
+          used).
 
         examples:
 
index 615b033c21a28b92aa1d48758f23faa1a7b945e8..37156d4fc8222005d82cfcbeeb763d2f57275c33 100644 (file)
@@ -3033,7 +3033,10 @@ The left\-hand side can be any general path expression; see \fBpath()\fR\.
 Note that the left\-hand side of \'|=\' refers to a value in \fB\.\fR\. Thus \fB$var\.foo |= \. + 1\fR won\'t work as expected (\fB$var\.foo\fR is not a valid or useful path expression in \fB\.\fR); use \fB$var | \.foo |= \. + 1\fR instead\.
 .
 .P
-If the right\-hand side outputs multiple values, only the last one will be used\.
+If the right\-hand side outputs no values (i\.e\., \fBempty\fR), then the left\-hand side path will be deleted, as with \fBdel(path)\fR\.
+.
+.P
+If the right\-hand side outputs multiple values, only the first one will be used (NOTE: it used to be that only the last one was used)\.
 .
 .IP "" 4
 .
index d6cd43212732069bfc93df551ffb9c630ddf213d..f7c6e9b773837a680ceff6aa4db5db7dffa810c5 100644 (file)
@@ -10,7 +10,7 @@ def min_by(f): _min_by_impl(map([f]));
 def add: reduce .[] as $x (null; . + $x);
 def del(f): delpaths([path(f)]);
 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 (.; label $out | (setpath($p; getpath($p) | update) | ., break $out), delpaths([$p]));
 def map_values(f): .[] |= f;
 
 # recurse