To begin with, my programming language, named Ignite, is a transpiled programming language and translates the Ignite Source File to a C++ source file.
Chained Comparison Operator is when you have comparison operators (such as <=
, !=
, >
, etc.) that are chained together, meaning that multiple of these operators are used in a single expression without introducing other logical operators to separate them. One example would be: x < y < z
.
The question is what black magic do I perform to interpret this expression as a valid expression in C++ IN a way that it aligns with Mathematics?
As of Python, it just simply adds an AND expression in between chained operators, so x < y < z
would become x < y && y < z
. It works good for simple cases as this one. My initial thought was to allow only one comparison operator at a time, so if you used <
for first operator in the chain, you have to use only <
in the proceeding ones in the chain. But this is not ideal because you can have this expression x < y <= z
as a valid Mathematical expression.
Okay... then if I allow mixing operators, x < y > z
is a valid operator chain but has no meaning in Mathematics (correct me if I am wrong). And this will be interpreted as x < y && y > z
.
But what if you have expression as x != y != z
? This is a valid Mathematical expression that says "x, y and z are not equal to each other". But interpreting it as x != y && y != z
would not be best description, as x
could still equal z
.
What I have came up with is to interpret it as x != y && x != z && x != z
, as comparing all the variables with all the others except itself. This works well when you have same type of operator. But quickly becomes problem for x < y <= z
. Which of the two (<
or <=
) would you use to compare x
with z
when interpreting?
So I have gone ahead and use both of the two operators and OR them, so it would interpret it as x < y && (x < z || x <= z) && y <= z
. But now what if you have a valid Mathematical expression x == y == z != 1
which means "x, y and z are all equal but not equal to 1". Using my logic would result in expression x == y && x == z && (x == 1 || x != 1) && y == z && (y == 1 || y != 1) && z != 1
... Thinking about it, it works... but is there a better way of doing it?
Thanks.
Simplicity is a feature for a programmation language and I think supporting all the expressions from your question is a level of complexity you do not want.
As was demonstrated in comments, expressions such as x != y != z
do not make it obvious if x != z
and the reason why it is not obvious is that!=
is not a transitive relation.
What I would recommend to you is:
a <op> b <op> c
if it implies a <op> c
.<op>
do not need to be the same everywhere BTW, for instance, from a < b = c <= d
, you can deduce something for all the pairs of variables:For a
: a < b, c, d
For b
: a < b
, b = c
, b <= d
For c
: a < c
b = c
, c <= d
For d
: see above.
Just having transitive operators is not enough, they must not have conflicting directions (do not mix <
/<=
with >
/>=
) and be applicable to all pairs of operands (e.g. what if, due to their type a < b makes sense, b = c too but a < c does not?).
For the reasoning, it should help if you search for an injective function / bijection f
from any type you define to real numbers.; if you find one, your type can be ordered since you can write a < b
iif f(a) < f(b)
.
x < y > z
where you mix operators you shouldn't, according to the above, there may be a smarter syntax to support the case.x, z < y
.At the end of the day, you could allow some subtle expressions such as:
0 < a,b <= c
meaning 0 < a && 0 < b && a <= c && b <= c
0 < c
is not tested.0 < a = b <= c
, slightly different, meaning 0 < a && a == b && b <= c
0 < b
, a <= c
and 0 < c
are not tested.