www.digitalmars.com         C & C++   DMDScript  

digitalmars.dip.ideas - `is in` expression

reply Quirin Schroll <qs.il.paperinik gmail.com> writes:
A new kind of binary expression that tests whether the left-hand 
side equals one of the right-hand values, or a range of values.

It allows expressing intent in a very concise manner, on par with 
other modern languages.



**Example:**
```d
if (age is in 13 .. 20) // teenager
```

**Grammar:**
```d
ShiftExpression is in ShiftExpression .. ShiftExpression
```

The first `ShiftExpression` is the *left-hand side*, the other 
two are called *lower* and *upper bound.*

**Semantics:**
It evaluates the left-hand side only once.
Equivalent to
```d
((auto ref lhs) => lowerBound <= lhs && lhs < upperBound)(lhsExpr)
```



**Examples:**
```d
if (color is in (red, green, blue)) { }

alias basicColors = AliasSeq!(red, green, blue);
if (color is in basicColors) { }
if (color is in (basicColors, yellow)) { }
```

**Grammar:**
```d
ShiftExpression is in ( Expression )
ShiftExpression is in ShiftExpression
```

**Semantics:**
If the right-hand side starts with a parenthesis, it’s a 
comma-separated list of options. Those options can be 
compile-time sequences which are expanded. Otherwise, the 
right-hand side must be a compile-time sequence.

Equivalent to:
```d
(auto ref lhs) {
     switch (lhs)
     {
         static foreach (enum option; AliasSeq!(options))
         {
      case option:
         }
         return true;
      default:
         return false;
     }
}(lhsExpression)
```
Sep 05
next sibling parent ltdk <khoa.alter.acc gmail.com> writes:
On Friday, 5 September 2025 at 12:12:22 UTC, Quirin Schroll wrote:
 A new kind of binary expression that tests whether the 
 left-hand side equals one of the right-hand values, or a range 
 of values.

 It allows expressing intent in a very concise manner, on par 
 with other modern languages.



 **Example:**
 ```d
 if (age is in 13 .. 20) // teenager
 ```

 **Grammar:**
 ```d
 ShiftExpression is in ShiftExpression .. ShiftExpression
 ```

 The first `ShiftExpression` is the *left-hand side*, the other 
 two are called *lower* and *upper bound.*

 **Semantics:**
 It evaluates the left-hand side only once.
 Equivalent to
 ```d
 ((auto ref lhs) => lowerBound <= lhs && lhs < 
 upperBound)(lhsExpr)
 ```
My stupid question: why not just 'in' ? Julia has 'in' operator working with ranges
Sep 05
prev sibling next sibling parent monkyyy <crazymonkyyy gmail.com> writes:
On Friday, 5 September 2025 at 12:12:22 UTC, Quirin Schroll wrote:
 A new kind of binary expression that tests whether the 
 left-hand side equals one of the right-hand values, or a range 
 of values.

 [...]
thats like 5 new ideas or not generic in the slightest
Sep 05
prev sibling next sibling parent Nick Treleaven <nick geany.org> writes:
On Friday, 5 September 2025 at 12:12:22 UTC, Quirin Schroll wrote:
 A new kind of binary expression that tests whether the 
 left-hand side equals one of the right-hand values, or a range 
 of values.

 It allows expressing intent in a very concise manner, on par 
 with other modern languages.

 Range of values

 Example:
 if (age is in 13 .. 20) // teenager
I thought there might be something for this in Phobos (e.g. std.comparison), but I couldn't find it. E.g.: `age.between(13, 20)`
 List of values
Is it significantly better than: https://dlang.org/phobos/std_algorithm_comparison.html#among ? `among` with runtime arguments also supports a predicate, so it's more flexible. ...
 **Semantics:**
 If the right-hand side starts with a parenthesis, it’s a 
 comma-separated list of options. Those options can be 
 compile-time sequences which are expanded.
Can the options be runtime values?
 Otherwise, the right-hand side must be a compile-time sequence.

 Equivalent to:
 ```d
 (auto ref lhs) {
     switch (lhs)
     {
         static foreach (enum option; AliasSeq!(options))
         {
      case option:
         }
         return true;
      default:
         return false;
     }
 }(lhsExpression)
 ```
Sep 07
prev sibling next sibling parent reply Atila Neves <atila.neves gmail.com> writes:
On Friday, 5 September 2025 at 12:12:22 UTC, Quirin Schroll wrote:
 A new kind of binary expression that tests whether the 
 left-hand side equals one of the right-hand values, or a range 
 of values.

 [...]
The party line until now has been to not support this because of performance, namely the fact that it would usually be O(N).
Sep 09
next sibling parent Quirin Schroll <qs.il.paperinik gmail.com> writes:
On Tuesday, 9 September 2025 at 11:07:42 UTC, Atila Neves wrote:
 On Friday, 5 September 2025 at 12:12:22 UTC, Quirin Schroll 
 wrote:
 A new kind of binary expression that tests whether the 
 left-hand side equals one of the right-hand values, or a range 
 of values.

 [...]
The party line until now has been to not support this because of performance, namely the fact that it would usually be O(N).
It depends on how you count. Since the list is a compile-time sequence, one could argue it’s O(1). The compiler could optimize it.
Sep 09
prev sibling parent reply Clouudy <Swergers123 gmail.com> writes:
On Tuesday, 9 September 2025 at 11:07:42 UTC, Atila Neves wrote:
 On Friday, 5 September 2025 at 12:12:22 UTC, Quirin Schroll 
 wrote:
 A new kind of binary expression that tests whether the 
 left-hand side equals one of the right-hand values, or a range 
 of values.

 [...]
The party line until now has been to not support this because of performance, namely the fact that it would usually be O(N).
As far as I know, this isn't true. Or at least not universally true. If you implement it as a set then it's possible to do some Bitmask magic, and it results in checks that are faster than if statements. At least that's how it's done in Pascal. And if you're doing groups of non-contiguous values like `if i in [0..3, 7, 9, 12..15] then`, it saves a lot of reading space, too. Of course this would only be constant-speed if it was a pre-defined set. I've actually had a similar use case for this within an emulator, where I had to combine a range and a nearby values within a switch statement, which could have been a lot more concise with sets. Even if there's a performance cost when using it for dynamic sets, I don't necessarily see the reason why it shouldn't be included. People are going to search the data structures in an O(N) manner regardless, and as long as it's not used within containers where the expectation is that everything is constant time, I don't see why the option shouldn't be present. You could just add it as an operator if you wanted to.
Sep 23
next sibling parent Clouudy <Swergers123 gmail.com> writes:
On Wednesday, 24 September 2025 at 01:34:06 UTC, Clouudy wrote:
 You could just add it as an operator if you wanted to.
Oh apparently it already is an operator. Well anyways most of my points still stand, I believe.
Sep 24
prev sibling parent Atila Neves <atila.neves gmail.com> writes:
On Wednesday, 24 September 2025 at 01:34:06 UTC, Clouudy wrote:
 On Tuesday, 9 September 2025 at 11:07:42 UTC, Atila Neves wrote:
 On Friday, 5 September 2025 at 12:12:22 UTC, Quirin Schroll 
 wrote:
 A new kind of binary expression that tests whether the 
 left-hand side equals one of the right-hand values, or a 
 range of values.

 [...]
The party line until now has been to not support this because of performance, namely the fact that it would usually be O(N).
As far as I know, this isn't true. Or at least not universally true.
Hence "usually".
 If you implement it as a set then it's possible to do some 
 Bitmask magic, and it results in checks that are faster than if 
 statements.
*Some* ranges will have good performance, yes.
 Even if there's a performance cost when using it for dynamic 
 sets, I don't necessarily see the reason why it shouldn't be 
 included. People are going to search the data structures in an 
 O(N) manner regardless,
Right, and the party line was that something like `countUntil` made that explicit. I'm not even arguing for what was said before, just explaining what the consensus was.
Sep 25
prev sibling parent Paul Backus <snarwin gmail.com> writes:
On Friday, 5 September 2025 at 12:12:22 UTC, Quirin Schroll wrote:
 A new kind of binary expression that tests whether the 
 left-hand side equals one of the right-hand values, or a range 
 of values.

 It allows expressing intent in a very concise manner, on par 
 with other modern languages.



 **Example:**
 ```d
 if (age is in 13 .. 20) // teenager
 ```
```d void checkAge(int age) { import std.range: interval = iota; import std.stdio: writeln; if (age in interval(1, 13)) writeln("child"); else if (age in interval(13, 20)) writeln("teenager"); else writeln("adult"); } void main() { checkAge(7); checkAge(16); checkAge(42); } ```
Sep 10