<p>How could an operator to test if a number is within a lower and upper bound? <a href="https://languagedesign.stackexchange.com/a/513/38">SQL seems to have this</a> as in <code>10 &lt;= x &lt;= 20</code>. However, if this were to be implemented in a C-style language there would be ambiguity with comparing the boolean/integer resulting from <code>10 &lt;= x</code> with <code>20</code> instead of actually being a proper ternary operator.</p>
<p>Although an algorithm could recognize such ternary <em>between</em> operators and programmers could use parenthesis to bypass them for whatever reason, what are some other syntactical options to implement such a <em>between</em> operator without ambiguity in the first place?</p>

<syntax><operators>
Unambiguous syntax for a ternary comparison operator
CC BY-SA 4.0
2023-05-20T00:59:17.440Z
Python, Julia, and some other languages support comparison chaining - you can do `x < y < z > k >= i == 2 < a`. The lexer probably just lexes it as a "sequence" of comparisons. Besides, there's not much reason to compare `10 <= x` and `20`.
naffetS
CC BY-SA 4.0
2023-05-20T03:24:23.183Z
For what it's worth, I think that syntax and semantics are interleaved in this question, and "implementation", while perhaps not ideal, encompassed that better than purely phrasing it in terms of syntax.
Michael Homer
<p>I would favor having a comparison operator yield a chainable comparison result which can be implicitly converted to Boolean or used in an overload of the comparison operators.  While chained comparisons are most commonly used to check whether one thing is within the range of two others, a single function would suffer from at least three significant limitations:</p>
<ol>
<li><p>Sometimes the range should include the right and and sometimes not, and the range should occasionally exclude the left edge.</p>
</li>
<li><p>While checking for ordering among three items may be the most common use case, it's not particularly uncommon to require that four or more items be properly sequenced, e.g. checking whether <code>a &lt;= b</code>, <code>b &lt;= c</code>, and <code>c &lt;= d</code> are all true, but perhaps with some <code>&lt;=</code> replaced with <code>&lt;</code>.</p>
</li>
<li><p>It's also not uncommon to want to check that multiple things are all equal to each other, and for this usage case checking three items would not be particularly more common than checking four.  Note that if a compiler wants to include particular logic for it, a multi-way comparison may be faster than a sequence of individual comparisons on some platforms.  For example, on an 8-bit platform, checking multiple <code>long</code> values against each other might be done most efficiently by comparing the least-significant byte of every value, and then the next byte of every value, etc.</p>
</li>
</ol>
<p>BTW, an alternative approach to passing code to evaluate the left-hand operand might be to provide a mechanism via which an expression can exit via one of two paths.  This would be awkward at the source code level, but could make things nice at the compiler level.  If something like:</p>
<pre><code>if (expr1) ...action1...; else ...action2...;
</code></pre>
<p>calling an &quot;evaluate branching instruction&quot; with <code>action1</code> and <code>action2</code> as the true and false targets, processing something like:</p>
<pre><code>if (expr1 || expr2) ...action1...; else ...action2...;
</code></pre>
<p>then <code>pipeOperator(leftExpr, rightExpr, trueAction, falseAction);</code> would involve <code>branchOperator(leftExpr, trueAction, branchOperator(rightExpr, trueAction, falseAction))</code>.  It might be possible to process chainable comparison operators similarly.</p>

CC BY-SA 4.0
2023-07-02T17:14:59.127Z
2023-07-02T17:14:59.127Z
supercat
<h1>Custom <code>between</code> operator</h1>
<p>You could have a two-operand operator, taking a number and a tuple or something like that:</p>
<pre><code>x between (10, 20)
</code></pre>
<p>You could also implement it as a ternary just like <code>a ? b : c</code>:</p>
<pre><code>x between 10 and 20
</code></pre>
<p>You can of course choose symbols, maybe Unicode, instead of the words <code>between</code> and <code>and</code>. I'm not sure if it would quite fit, but <code>≬</code>, U+226C is called &quot;BETWEEN&quot;.</p>
<p>Another idea:</p>
<pre><code>x ∈ 10..20
</code></pre>

CC BY-SA 4.0
2023-05-20T01:04:35.643Z
2023-05-20T01:04:35.643Z
naffetS
CC BY-SA 4.0
2023-07-02T18:10:10.633Z
Python does this with range:
`3 in range(1,5) == True`
kouta-kun
<p>There are several plausible approaches here, some of which work with the ambiguity and some sidestep it entirely. Some imply significant semantic choices about the language more broadly.</p>
<ul>
<li><p>A function, or special builtin, like <code>between(x, a, b)</code>. This is uninteresting but always practical.</p>
</li>
<li><p>A bespoke containment operator: <code>x between 3 and 9</code>. Simple syntax extension.</p>
</li>
<li><p>Special parser support for comparison operator chains. This is what Python does, for example: <code>x &lt; y &lt; z</code> tests whether y is within that range rather than being treated as <code>(x &lt; y) &lt; z</code>. In practice, people reading it do understand what's meant without thinking about it and without expecting the parse you mention, and the implementation is straightforward.</p>
</li>
<li><p>Disconnect boolean truth from the underlying value. This is something you can do in Raku (Perl 6), though it isn't how its basic comparison operators work: <code>0 but True</code> is the number zero but <em>also a true value when used as a boolean</em>, and <code>10 but False</code> is the number ten but also a false value.</p>
<p>The comparison operator can then return such a value, so <code>3 &lt; 4</code> returns a true 4, and <code>3 &lt; 4 &lt; 2</code> computes 4 &lt; 2 and returns a false 2. This relies on exactly the <code>(3 &lt; 4) &lt; 2</code> parse that you identify, but makes it work instead.</p>
</li>
<li><p>Distinguish the operator (overload) in use by the expected <em>type</em> in its context. In <code>2 &lt; x &lt;= 4</code>, the language sees that <code>&lt;=</code> expects a number on the left, and uses an overload of <code>&lt;</code> that returns the right-hand side or short-circuits. Short-circuiting may necessitate a broader semantic change, and overloading by <em>expected</em> type is relatively unusual.</p>
</li>
<li><p>Range <em>values</em> that you can test element-of. This is like the mathematical approach of <code>x ∈ (3, 7]</code>, so <code>x in range(4, 8)</code> or <code>(2..10).has(x)</code>. These may be expected to be iterable, which is awkward for non-integer ranges, and they are clunky for non-numeric types.</p>
</li>
<li><p>Mixfix/multi-part operator names. In this case, <code>&lt; ... &lt;</code> would be a <em>single operator</em>, like a Smalltalk method <code>between: and:</code>. This is a pervasive change to the language, rather than a special case.</p>
</li>
<li><p>Mixfix function or method names, exactly like Smalltalk: <code>x.between: 3 and: 7</code>. This is also a deep-reaching change, but perhaps somewhat less invasive than for operators.</p>
</li>
</ul>
<p>All of these could be defensible in the right language, but it doesn't seem worthwhile extending a language without mixfix names to have them, for example, just to support range inclusion.</p>

CC BY-SA 4.0
2023-05-20T02:20:25.663Z
2023-05-20T02:20:25.663Z
Michael Homer
CC BY-SA 4.0
2023-07-02T03:23:51.663Z
"These may be expected to be iterable, which is awkward for non-integer ranges" -- Swift's solution: `Range<Bound>`  is only iterable `where Bound: Strideable, Bound.Stride: SignedInteger`. `Double.Stride == Double`, so `Range<Double>` is not iterable.
Bbrk24
CC BY-SA 4.0
2023-07-02T18:34:20.687Z
FYI, Python actually implements "element-of" for range and its' various options so you can do `5 in range(1,7,2) == True`
kouta-kun
# Unambiguous syntax for a ternary comparison operator
Posted by: username_0 on 2023-05-20
How could an operator to test if a number is within a lower and upper bound? [SQL seems to have this](https://languagedesign.stackexchange.com/a/513/38) as in `10 <= x <= 20`. However, if this were to be implemented in a C-style language there would be ambiguity with comparing the boolean/integer resulting from `10 <= x` with `20` instead of actually being a proper ternary operator.

Although an algorithm could recognize such ternary *between* operators and programmers could use parenthesis to bypass them for whatever reason, what are some other syntactical options to implement such a *between* operator without ambiguity in the first place?
**Tags:** syntax operators
> **Comments:**
> **username_1**: Python, Julia, and some other languages support comparison chaining - you can do `x < y < z > k >= i == 2 < a`. The lexer probably just lexes it as a "sequence" of comparisons. Besides, there's not much reason to compare `10 <= x` and `20`.  
> **username_2**: For what it's worth, I think that syntax and semantics are interleaved in this question, and "implementation", while perhaps not ideal, encompassed that better than purely phrasing it in terms of syntax.  
---
## 3 answers
### Answer by username_2 on 2023-05-20. Score: 13 | Accepted answer
There are several plausible approaches here, some of which work with the ambiguity and some sidestep it entirely. Some imply significant semantic choices about the language more broadly.

* A function, or special builtin, like `between(x, a, b)`. This is uninteresting but always practical.
* A bespoke containment operator: `x between 3 and 9`. Simple syntax extension.
* Special parser support for comparison operator chains. This is what Python does, for example: `x < y < z` tests whether y is within that range rather than being treated as `(x < y) < z`. In practice, people reading it do understand what's meant without thinking about it and without expecting the parse you mention, and the implementation is straightforward.
* Disconnect boolean truth from the underlying value. This is something you can do in Raku (Perl 6), though it isn't how its basic comparison operators work: `0 but True` is the number zero but *also a true value when used as a boolean*, and `10 but False` is the number ten but also a false value.

  The comparison operator can then return such a value, so `3 < 4` returns a true 4, and `3 < 4 < 2` computes 4 < 2 and returns a false 2. This relies on exactly the `(3 < 4) < 2` parse that you identify, but makes it work instead.
* Distinguish the operator (overload) in use by the expected *type* in its context. In `2 < x <= 4`, the language sees that `<=` expects a number on the left, and uses an overload of `<` that returns the right-hand side or short-circuits. Short-circuiting may necessitate a broader semantic change, and overloading by *expected* type is relatively unusual.
* Range *values* that you can test element-of. This is like the mathematical approach of `x ∈ (3, 7]`, so `x in range(4, 8)` or `(2..10).has(x)`. These may be expected to be iterable, which is awkward for non-integer ranges, and they are clunky for non-numeric types.
* Mixfix/multi-part operator names. In this case, `< ... <` would be a *single operator*, like a Smalltalk method `between: and:`. This is a pervasive change to the language, rather than a special case.
* Mixfix function or method names, exactly like Smalltalk: `x.between: 3 and: 7`. This is also a deep-reaching change, but perhaps somewhat less invasive than for operators.

All of these could be defensible in the right language, but it doesn't seem worthwhile extending a language without mixfix names to have them, for example, just to support range inclusion.
> **Comments:**
> **username_5** (2023-07-02): "These may be expected to be iterable, which is awkward for non-integer ranges" -- Swift's solution: `Range<Bound>`  is only iterable `where Bound: Strideable, Bound.Stride: SignedInteger`. `Double.Stride == Double`, so `Range<Double>` is not iterable.  
> **username_4** (2023-07-02): FYI, Python actually implements "element-of" for range and its' various options so you can do `5 in range(1,7,2) == True`  
---
### Answer by username_1 on 2023-05-20. Score: 3
Custom between operator
You could have a two-operand operator, taking a number and a tuple or something like that:
x between (10, 20)

You could also implement it as a ternary just like a ? b : c:
x between 10 and 20

You can of course choose symbols, maybe Unicode, instead of the words between and and. I'm not sure if it would quite fit, but ≬, U+226C is called "BETWEEN".
Another idea:
x ∈ 10..20
> **Comments:**
> **username_4** (2023-07-02): Python does this with range:
`3 in range(1,5) == True`  
---
### Answer by username_3 on 2023-07-02. Score: 2
I would favor having a comparison operator yield a chainable comparison result which can be implicitly converted to Boolean or used in an overload of the comparison operators.  While chained comparisons are most commonly used to check whether one thing is within the range of two others, a single function would suffer from at least three significant limitations:

Sometimes the range should include the right and and sometimes not, and the range should occasionally exclude the left edge.

While checking for ordering among three items may be the most common use case, it's not particularly uncommon to require that four or more items be properly sequenced, e.g. checking whether a <= b, b <= c, and c <= d are all true, but perhaps with some <= replaced with <.

It's also not uncommon to want to check that multiple things are all equal to each other, and for this usage case checking three items would not be particularly more common than checking four.  Note that if a compiler wants to include particular logic for it, a multi-way comparison may be faster than a sequence of individual comparisons on some platforms.  For example, on an 8-bit platform, checking multiple long values against each other might be done most efficiently by comparing the least-significant byte of every value, and then the next byte of every value, etc.


BTW, an alternative approach to passing code to evaluate the left-hand operand might be to provide a mechanism via which an expression can exit via one of two paths.  This would be awkward at the source code level, but could make things nice at the compiler level.  If something like:
if (expr1) ...action1...; else ...action2...;

calling an "evaluate branching instruction" with action1 and action2 as the true and false targets, processing something like:
if (expr1 || expr2) ...action1...; else ...action2...;

then pipeOperator(leftExpr, rightExpr, trueAction, falseAction); would involve branchOperator(leftExpr, trueAction, branchOperator(rightExpr, trueAction, falseAction)).  It might be possible to process chainable comparison operators similarly.
---
