Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Absent variable on left side of boolean OR (||) expression should make it absent #1430

Closed
hchargois opened this issue Nov 24, 2023 · 1 comment · Fixed by #1434
Closed

Absent variable on left side of boolean OR (||) expression should make it absent #1430

hchargois opened this issue Nov 24, 2023 · 1 comment · Fixed by #1434

Comments

@hchargois
Copy link

Compare these filter expressions:

$ echo 'a=1' | mlr filter '$a > 0 || $b'
a=1
$ echo 'a=1' | mlr filter '$b || $a > 0'
(no output)

The second one is extremely surprising to me, and I would say, incorrect.

Firstly, because I expect an OR expression to be true if any side is true, regardless of whether the other is false, absent, null or whatnot. Secondly, I expect an OR expression to produce the same truth value regardless of the order of the operands.

Finally, because even after taking time to read the doc, I still don't understand why this would be correct.

The doc on absent values [1] says

boolean operators with both operands being absent evaluate to absent

But here we only have one absent operand, not both

Arithmetic operators with one absent operand return the other operand

I would expect the same of ||, but granted I would not expect it from &&

If you're interested in a formal description of how empty and absent fields participate in arithmetic, here's a table for plus (other arithmetic/boolean/bitwise operators are similar)

The table seems perfectly symmetrical, so I would expect the same symmetry for operands of ||

[1] https://miller.readthedocs.io/en/latest/reference-main-null-data/

@johnkerl johnkerl self-assigned this Nov 26, 2023
@johnkerl johnkerl changed the title Absent variable on left side of boolean OR (||) expression makes it absent Absent variable on left side of boolean OR (||) expression should make it absent Dec 2, 2023
@johnkerl
Copy link
Owner

johnkerl commented Dec 2, 2023

@hchargois thank you for the report!!

With #1434 I have:

$ echo 'a=1' | mlr filter '$a > 0 || $b'
a=1

$ echo 'a=1' | mlr filter '$b || $a > 0'
a=1

and more generally:

$ echo x=1 | mlr filter 'true || nonesuch'
x=1

$ echo x=1 | mlr filter 'nonesuch || true'
x=1

$ echo x=1 | mlr filter 'false || nonesuch'

$ echo x=1 | mlr filter 'nonesuch || false'

Also:

(+)        | 1          2.5        true      (empty)    (absent)   (error)
------     + ------     ------     ------     ------     ------     ------
1          | 2          3.5        (error)    1          1          (error)
2.5        | 3.5        5          (error)    2.5        2.5        (error)
true       | (error)    (error)    (error)    (error)    (error)    (error)
(empty)    | 1          2.5        (error)    (empty)    (absent)   (error)
(absent)   | 1          2.5        (error)    (absent)   (absent)   (error)
(error)    | (error)    (error)    (error)    (error)    (error)    (error)

(&&)       | true       false      3         (empty)    (absent)   (error)
------     + ------     ------     ------     ------     ------     ------
true       | true       false      (error)    (error)    (absent)   (error)
false      | false      false      false      false      false      false
3          | (error)    (error)    (error)    (error)    (absent)   (error)
(empty)    | true       false      (error)    (error)    (absent)   (error)
(absent)   | true       false      (error)    (absent)   (absent)   (error)
(error)    | (error)    (error)    (error)    (error)    (error)    (error)

(||)       | true       false      3         (empty)    (absent)   (error)
------     + ------     ------     ------     ------     ------     ------
true       | true       true       true       true       true       true
false      | true       false      (error)    (error)    (absent)   (error)
3          | (error)    (error)    (error)    (error)    (absent)   (error)
(empty)    | true       false      (error)    (error)    (absent)   (error)
(absent)   | true       false      (error)    (absent)   (absent)   (error)
(error)    | (error)    (error)    (error)    (error)    (error)    (error)

This is largely the same for && and || as it is with + with notable exceptions. In particular, true-or-error must be true, and false-and-error must be false, because of the short-circuiting guarantee -- we could only determine the right-hand side is error by evaluating it, but we must not evaluate the right-hand side in these cases, in order to satisfy the guarantee of short-circuiting semantics.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging a pull request may close this issue.

2 participants