How to assign and compare arrays to SumType?

Steven Schveighoffer schveiguy at gmail.com
Tue Jun 11 22:54:50 UTC 2024


On Tuesday, 11 June 2024 at 16:41:46 UTC, confuzzled wrote:
> Comparison between a Variant and an array is straightforward. 
> How does one accomplish the same between a SumType and an array?
>
> ```d
> import std.variant;
> import std.sumtype;
> import std.stdio;
>
> struct S
> {
>     SumType!(double[]) data;  // {1}
> }
>
> void main()
> {
>     Variant v = [1.7, 2.7, 3.7, 4.7, 5.7];
>     assert(v == [1.7, 2.7, 3.7, 4.7, 5.7]);
>
>     S s;
>     s.data = [1.7, 2.7, 3.7, 4.7, 5.7]; // {2}
>     assert(s.data == [1.7, 2.7, 3.7, 4.7, 5.7]);
> }
> ```
>
> Resulting Error:
>
>> var.d(17): Error: template \`opEquals\` is not callable using 
>> argument types `!()(double[])`
>> /Users/anju/dlang/dmd-2.109.0-beta.1/osx/bin/../../src/phobos/std/sumtype.d(712):        Candidate is: `opEquals(this This, Rhs)(auto ref Rhs rhs)`
>>  with `This = SumType!(double[]),
>>       Rhs = double[]`
>>  must satisfy the following constraint:
>>`       !is(CommonType!(This, Rhs) == void)`
>
> Also, assuming that {1} read "SumType!(double)[] data;", what 
> would be the proper way to accomplish the assignment at {2} and 
> the subsequent comparison.

`SumType` requires you unwrap to the correct type in order to use 
it.

The function that unwraps a `SumType` is called `match`. The 
`match` function accepts a sumtype and a list of processors. Each 
processor is tried in order, based on the actual stored type, and 
the first one that compiles will be used.

Your `SumType` has only one type, but just to illustrate how it 
would work:

```d
assert(s.data.match!((double[] darr) => darr == [1.7, 2.7, 3.7, 
4.7, 5.7]));
```

What this is doing is, if the actual type is a `double[]`, then 
call the first function, and return it's value (a boolean).

Because there are no other types, this will work. If you have 
more than one type, your list of lambdas must be exhaustive. That 
is, at least one of the functions must match for each type. And 
also, functions that won't ever be used are rejected.

Let's see how it works if you want to both check that the value 
is a `double[]` and that it matches your value:

```d
SumType!(double[], int) s = [1.7, 2.7, 3.7, 4.7, 5.7];
assert(s.data.match!(
         (double[] darr) => darr == [1.7, 2.7, 3.7, 4.7, 5.7]),
         _ => false // any other type
     )
);
s = 5; // switch to int
assert(!s.data.match!(
         (double[] darr) => darr == [1.7, 2.7, 3.7, 4.7, 5.7]),
         _ => false // any other type
     )
);
```

`SumTypes` take some getting used to. It can get pretty verbose 
to use `match`.

-Steve


More information about the Digitalmars-d-learn mailing list