Skip to content

Commit

Permalink
Tolerate and pass through null from AND [...], OR [...]
Browse files Browse the repository at this point in the history
The enfix AND and OR actions get some amount of flexibility from
behaving differently if their right hand side is a GROUP! or a BLOCK!.
Concept is that the right hand side is quoted, and then it is not run
if the left hand side precludes the need to run it.  GROUP! indicates
the result should be forced to LOGIC!, and a BLOCK! indicates a more
general willingness to take whatever type got evaluated to.

This commit takes the difference a little further, by introducing null
tolerance to the BLOCK! version.  It's not legal to say `() or ()`, but
it is legal to say `() or []`, thus producing a null result.  This
means falsey operations which use the BLOCK! on the right do not end
up canonized to a BLANK! the way that an ALL or ANY would.

So a falsey result (considering nulls falsey) will fall through
unmodified.  Someone can write:

    x: false
    x: me and [1 + 2]

And x will be false...not a BLANK! as it would have been before.  Or

    x: true
    x: me and []

This means that x will be null, not a BLANK! as it would have been
before.

The "ME AND" and "ME OR" patterns are motivating for the example, so
that the state of the "me" variable is preserved instead of forced to
a blank.  This produces some truthy-oriented variations for DEFAULT.

The consequences of this change are not yet well-understood, but given
the relative recent addition of AND and OR it's worth trying.
  • Loading branch information
hostilefork committed May 14, 2018
1 parent 530d654 commit 86e4724
Show file tree
Hide file tree
Showing 2 changed files with 24 additions and 21 deletions.
43 changes: 23 additions & 20 deletions src/mezz/base-infix.r
Expand Up @@ -300,40 +300,40 @@ else*: enfix redescribe [
and: enfix func [
{Short-circuit boolean AND, which can also pass thru non-LOGIC! values}

return: [any-value!]
{LOGIC! if right arg is GROUP!, else right arg or blank}
left [any-value!]
return: [<opt> any-value!]
{LOGIC! if right arg is GROUP!, else falsey left arg or right arg}
left [<opt> any-value!]
{Expression which will always be evaluated}
:right [group! block!]
{Quoted expression, evaluated unless left is blank or FALSE}
][
if all [block? :left semiquoted? 'left] [
fail/where "left hand side of AND should not be literal block" 'left
]
either group? right [
did all [:left | really* do right]
either* group? right [
did all [really* :left | really* do right]
][
all [:left | try do right]
either* not :left [:left] [do right] ;-- preserve exact falsey value
]
]

or: enfix func [
{Short-circuit boolean OR, which can also pass thru non-LOGIC! values}

return: [any-value!]
{LOGIC! if right arg is GROUP!, else left or right value or blank}
left [any-value!]
return: [<opt> any-value!]
{LOGIC! if right arg is GROUP!, else truthy left arg or right arg}
left [<opt> any-value!]
{Expression which will always be evaluated}
:right [group! block!]
{Quoted expression, evaluated only if left is blank or FALSE}
][
if all [block? :left semiquoted? 'left] [
fail/where "left hand side of OR should not be literal block" 'left
]
either group? right [
did any [:left | really* do right]
either* group? right [
did any [really* :left | really* do right]
][
any [:left | try do right]
either* did :left [:left] [do right] ;-- preserve exact falsey value
]
]

Expand All @@ -342,25 +342,28 @@ xor: enfix func [

return: [any-value!]
{LOGIC! if right arg is GROUP!, else left or right value or blank}
left [any-value!]
left [<opt> any-value!]
{Expression which will always be evaluated, guides result value}
:right [group! block!]
{Quoted expression, must be always evaluated as well}
][
if all [block? :left semiquoted? 'left] [
fail/where "left hand side of XOR should not be literal block" 'left
]
either group? right [
did either not :left [
really do right

right: do right ;-- gets evaluated regardless

either* group? right [
either not really* :left [
did really* :right
][
all [not really* do right | :left]
did all [not really* :right | :left]
]
][
either not :left [
do right
either* not :left [
either did :right [:right] [_]
][
all [not really* do right | :left]
either* did :right [_] [:right]
]
]
]
Expand Down
2 changes: 1 addition & 1 deletion src/mezz/mezz-help.r
Expand Up @@ -208,7 +208,7 @@ spec-of: function [
]
if return-type or (return-note) [
keep compose/only [
return: (opt return-type) (opt return_note)
return: (opt return-type) (opt return-note)
]
]

Expand Down

0 comments on commit 86e4724

Please sign in to comment.