I would like to implement ternary operator in my code (cond ? x : y). I am not going to use as alias for if expression, I plan to use it for some vectorized masked blends, however I am having problems with operator precedence, I managed to do cond ? (x : y), but not cond ? x : y.
I do recall I have seen presentation demonstrating how to do it properly. Likely, it was Araq's presentation, but I can't find it now.
I don't think it's possible, actually. By using pars, you force non-standard operator (let's assume : could be an operator) precedence. Then, it's possible for ? to just eat an untyped block, not caring too deeply about whenever : is really an operator or not. But without pars, things are different.
The only thing I can think of is using a visually similar cond ? x ::: y and then:
macro `:::`(a, b): untyped =
a.expectKind nnkInfix
a.expectLen 3
assert $(a[0].ident) == "?"
let cond = a[1]
let lhs = a[2]
let rhs = b
template impl(a,b,c) = # here comes your implementation
# I'll just use if-else as an example
if a:
b
else:
c
result = getAst(impl(cond,lhs,rhs))
# example usage
let
a = 7
b = 3
x = (a > b ? a ::: b)
echo x
If you don't mind the eager evaluation, you can even do it without macros. This way of doing things tends to compose much better:
type
BranchPair[T] = object
then, otherwise: T
# This cannot be a template yet, buggy compiler...
proc `!`*[T](a, b: T): BranchPair[T] {.inline.} = BranchPair[T](then: a, otherwise: b)
template `?`*[T](cond: bool; p: BranchPair[T]): T =
(if cond: p.then else: p.otherwise)
echo(true ? 3 ! 4)