Thread overview
In Expressions
Mar 04, 2017
Andrey
Mar 04, 2017
John Colvin
Mar 04, 2017
Andrey
Mar 05, 2017
Basile B.
Mar 04, 2017
Meta
March 04, 2017
Hello, is there any way to using in expression like in python, e.g.
> if 4 in [1, 3, 4]:
>     do something

My code in D
> if (regionAlign in [RegionAlign.top, RegionAlign.bottom]) {
>    ...
> }

throws an error:
> incompatible types for (((cast(Widget)this).regionAlign()) in ([top, bottom])): 'RegionAlign' and 'RegionAlign[]'
March 04, 2017
On Saturday, 4 March 2017 at 17:11:46 UTC, Andrey wrote:
> Hello, is there any way to using in expression like in python, e.g.
>> if 4 in [1, 3, 4]:
>>     do something
>
> My code in D
>> if (regionAlign in [RegionAlign.top, RegionAlign.bottom]) {
>>    ...
>> }
>
> throws an error:
>> incompatible types for (((cast(Widget)this).regionAlign()) in ([top, bottom])): 'RegionAlign' and 'RegionAlign[]'

The in operator is defined for associative arrays, but not for normal arrays/slices.

You could do this:

import std.algorithm : canFind;
if ([RegionAlign.top, RegionAlign.bottom].canFind(regionAlign)) {
}

Consider using only(RegionAlign.top, RegionAlign.bottom) instead of [] to avoid allocating a temporary array.

import std.algorithm : canFind;
if (only(RegionAlign.top, RegionAlign.bottom).canFind(regionAlign)) {
}

but to be honest, I would just repeat myself a bit and write

if (regionAlign == RegionAlign.top ||
    regionAlign == RegionAlign.bottom) {
}

If you *really* must have `in`, you could wrap your arrays (or other ranges) in this:

import std.range : isInputRange;

struct WithInOp(alias eqPred = "a == b", Range)
if (isInputRange!Range)
{
    Range range;
    alias range this;
    bool opBinaryRight(string op : "in", T)(T rhs)
    {
        import std.algorithm.searching : canFind;
        return range.canFind!eqPred(rhs);
    }
}

auto withInOp(alias eqPred = "a == b", Range)(Range range)
{
    return WithInOp!(eqPred, Range)(range);
}

unittest
{
    auto r = withInOp([1, 2, 4]);
    assert(1 in r);
    assert(3 !in r);
    assert([1, 2] in r);
    assert([2, 2] !in r);

    struct S
    {
        int main, extra;
    }

    auto r2 = withInOp!"a.main == b.main"([S(1, 3), S(2, 4), S(4, 1)]);
    assert(S(1, 7) in r2);
    assert(S(3, 4) !in r2);
    assert([S(2, -42), S(4, 3)] in r2);
    assert([S(2, -42), S(3, 3)] !in r2);
}
March 04, 2017
On Saturday, 4 March 2017 at 17:11:46 UTC, Andrey wrote:
> Hello, is there any way to using in expression like in python, e.g.
>> if 4 in [1, 3, 4]:
>>     do something
>
> My code in D
>> if (regionAlign in [RegionAlign.top, RegionAlign.bottom]) {
>>    ...
>> }
>
> throws an error:
>> incompatible types for (((cast(Widget)this).regionAlign()) in ([top, bottom])): 'RegionAlign' and 'RegionAlign[]'

The reason this is disallowed for normal arrays is that finding a key in an array is O(n) while finding a key in an associative array is O(1). Rather than let users unknowingly write code that looks the same but is far slower for arrays, D doesn't allow this. You can use std.algorithm.among, however.

import std.algorithm;

if (regionAlign.among!(RegionAlign.top, RegionAlign.bottom))
{
    //etc.
}

http://dlang.org/phobos/std_algorithm_comparison.html#.among
March 04, 2017
On Saturday, 4 March 2017 at 17:57:16 UTC, John Colvin wrote:
> but to be honest, I would just repeat myself a bit and write
>
> if (regionAlign == RegionAlign.top ||
>     regionAlign == RegionAlign.bottom) {
> }

That's exactly what I did, just wondered - how to do such a thing.
Thank's for the detailed explanation.
March 05, 2017
On Saturday, 4 March 2017 at 19:31:46 UTC, Andrey wrote:
> On Saturday, 4 March 2017 at 17:57:16 UTC, John Colvin wrote:
>> but to be honest, I would just repeat myself a bit and write
>>
>> if (regionAlign == RegionAlign.top ||
>>     regionAlign == RegionAlign.bottom) {
>> }
>
> That's exactly what I did, just wondered - how to do such a thing.
> Thank's for the detailed explanation.

Run this through DUB:

```
/+dub.sdl:
name "dub_script"
dependency "iz" version="~master"
+/
module dub_script;

enum RegionAlign
{
    top, botttom, left, right
}

import iz.enumset;
alias Set = EnumSet!(RegionAlign, Set8);

void main(string[] args)
{
    with(RegionAlign)
    {
        Set set = [top, left];
        assert(top in set);
        assert(left in set);
    }
}
```

iz.enumset.EnumSet seems to be what you need. (assuming Region align is a named enum...)