Home > Uncategorized > 2 + 2 = 3

## 2 + 2 = 3

No really, when building a custom tenary operator I found that when combining two infix operators that both take 2 arguments I could emulate a tenary operator that takes 3 arguments.

But let’s start with the beginning. While looking at Pod::To::BigPage I was wondering if I ask for the right thing.

`(\$node.caption ?? '<caption>' ~ \$node.caption.&handle() ~ '</caption>' !! '' )`

Do I really want to check for trueness or would defindness be more appropriate? It would be easy to fix.

`(\$node.caption.defined ?? '<caption>' ~ \$node.caption.&handle() ~ '</caption>' !! '' )`

Problem solved. Well, somehow it doesn’t feel right to require a method call given that we got control structures with `with/without` and operators like `//` that check for defindness. Also there is no guarantee that a true thing is also defined.

```say [0.Bool, 0.defined]; # putting arguments of say into []
# OUTPUT«[False True]␤»  # will put a whitespace between elements```

Also, undefined things can be true.

```my \$v = Any but True;
say [\$v.Bool, \$v.defined];
# OUTPUT«[True False]␤»```

So why not define a tenary operator that tests for definedness? Because Rakudo wont let us just yet. Defining two infix operators that are chained is quite easy though.

```sub infix:<?//>(\a, \b -->DefinedAlternationContainer) { ??? }
sub infix:<!!>(DefinedAlternationContainer:D \cont, \b) { ??? }```

We have to make sure that we don’t collide with any other module that provides such an operator (we would need a multi sub). This can be done with an intermediary type that binds the two together.

```class DefinedAlternationContainer {
has \$.item;
has \$.condition-was-defined;
}```

It holds the second argument and the result of the condition from the first infix. Which is used by the 2nd infix to decided if third tenary operand or the the 2nd is returned. So we can write:

```my \$falsish = 2 but False;
say \$falsish ?// <defined> !! <undefined>;
# OUTPUT«defined␤»```

For your convenience I took the liberty write a module, put it into the ecosystem and on github.

Categories: Uncategorized