Search code examples
language-design

How can I implement Chained Comparison Operator support for my Programming Language?


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.


Solution

  • 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, expression such as x != y != z does 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:

    1. Only allow to chain operators a <op> b <op> c if it implies a <op> c.
      The operators <op> do not need to be the same 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 have the same direction too (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?). By nature, any type for which there exists a bijection f to a subset of real numbers can be ordered; for instance a < b iif f(a) < f(b).

    Short proof: Since all pairs of real numbers can be ordered and there exists a bijection between your type and a subset of the real numbers, then your type can be ordered too.

    1. For the case x < y > z where you mix operators you shouldn't, according to the above, there may be a smarter syntax to support the case.
      The proposed syntax is 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 <= d
    • 0 < a = b <= c, slightly different, meaning 0 < a && a == b && b <= c