While writing a Perl statement like if ( $foo >= X && $foo <= Y )
yet again, I wondered why many programming languages do not support the more comfortable form if ( X <= $foo <= Y )
and what this is called. I came up with “3-legged comparison” but no results when searching for it. By the way there is also the “element-of-set” form if ( $foo in X..Y )
which I only consider more readable when provided via a short keyword.
Is there a term for X <= $foo <= Y
comparison? Which languages support it?
3
I’d call it an n-ary comparison.
Operators that work on arbitrary numbers of operands are called “n-ary” operators:
n-ary
From a mathematical point of view, a function of n arguments can always be considered as a function of one single argument which is an element of some product space. However, it may be convenient for notation to consider n-ary functions, …
The same is true for programming languages, where functions taking several arguments could always be defined as functions taking a single argument of some composite type such as a tuple, or in languages with higher-order functions, by currying.
- Binary means 2-ary.
- …
- n-ary means n operands (or parameters), but is often used as a synonym of “polyadic”.
Python has an n-ary <
operator. Section 5.6 of the language docs says:
Unlike C, all comparison operations in Python have the same priority, which is lower than that of any arithmetic, shifting or bitwise operation. Also unlike C, expressions like
a < b < c
have the interpretation that is conventional in mathematics:Formally, if
a
,b
,c
, …,y
,z
are expressions and op1, op2, …, opN are comparison operators, thena
op1b
op2c
…y
opNz
is equivalent toa
op1b
and
b
op2c
and
…y
opNz
, except that each expression is evaluated at most once.
SQL has a native bounds/range check operator:
SELECT * FROM foo WHERE foo.bar BETWEEN 1 AND 100
Checking whether a value is within a certain range makes sense in SQL due to the algebraic nature of relational databases.
When it comes to programming languages though, there’s an order of operations and ( X <= $foo <= Y )
would normally be interpreted as ( ( X <= $foo ) <= Y ) )
, which is a quite different than ( $foo >= X && $foo <= Y )
. To get a sweet & simple range check operator we would have to tell the parser to ignore the order of operations for this very specific case, and that would go against the principle of least astonishment.
Not worth the trouble and the potential confusion for something that’s of extremely little benefit, just syntactic sugar really. If you find yourself doing range checks very often and don’t care for typing a few extra characters, you can always write a short function to take care of the comparisons for you.
1
Most PLC languages include some kind of instruction that does this. In RSLogix it’s called the LIM
instruction (see pg 3-5). It takes 3 inputs: a Low Lim
, Test
, and High Lim
value and returns a true/false output.
Note that you can provide parameters where Low Lim
is higher than High Lim
then it changes to an OR condition. That is, the output is true if the input is higher than Low Lim
OR lower than High Lim
. This makes sense when you consider many times you might have a 12 or 16-bit encoder on a rotary axis so the value zero is adjacent to the highest possible value.
Also, other languages, e.g. TwinCAT, have a LIMIT
instruction that outputs a coerced value instead of a boolean. That is, its purpose is to give you an output within the specified limits, or one of the limits themselves if the input is outside the specified limits. I believe this function is similar to the saturation function in Matlab/Simulink.
In both cases you could just create your own function to do this from the available primitives, so I can see why including such an operator might be considered superfluous.
In languages like C, a < b < c is compiled as
(a<b) < c
a<b evaluates to 0 or 1, so you end up executing
(1 < c) or (0 < c)
which is almost certainly not what you want.
In languages less brain damaged than C, you can be saved by the
type system, because (a < b) returns true or false, and (false < c)
is not a valid expression.
I can’t think offhand of any languages that implement this ternary operator
the way you expect, but it would be dangerous to use it if it exists, if only
because so many other languages will screw you.
1
In english it’s called “between inclusive”.
Microsoft’s T-SQL gives special syntax for it
select * from User where Age between 18 and 25