yq icon indicating copy to clipboard operation
yq copied to clipboard

Value operator can replace empty stream with single value

Open kanwren opened this issue 2 years ago • 0 comments

Split from #1515

The value operator (when a value is used as a constant-valued function, like . | "foo") should replace each value in its input stream with the given value, producing an output stream of the same length as the input. However, when given an empty input stream (what jq calls empty), instead of producing an empty output stream, they instead produce an output stream with one copy of the given value.

This breaks some intuitive invariants, like that for any array arr and operator f, that (arr | map(f) | length) == (arr | length), since map(f)[.[] | f]. This is how I found it in the first place; I was surprised when extra empty values appeared deep in a query after a map operation.

  • Version of yq: tested with 4.30.8 (unexpected behavior) and 3.1.0 (expected behavior)
  • Operating system: tested on macOS and Linux
  • Installed via: built from source

Input Yaml

data1.yml:

[]

Command

yq eval '.[] | "foo"' data1.yml

Actual behavior

The empty stream is replaced with a value:

foo

Expected behavior

The empty stream is mapped over, producing an empty output stream:

Additional context

Expected behavior is present in yq 3 (try yq -n '[] | .[] | "foo"') and jq (try jq -n 'empty | "foo"'). Note that in #1515, arrays and objects used as value operators had the expected behavior with multi-valued streams; with empty streams, however, they have the same unexpected behavior (replacing empty streams with a single value) as other values.

kanwren avatar Jan 16 '23 00:01 kanwren