Python's list equivalent with std.variant?

jfondren julian.fondren at gmail.com
Sun Oct 3 23:14:21 UTC 2021


On Sunday, 3 October 2021 at 22:22:48 UTC, rjkilpatrick wrote:
> ```d
> void main() {
>     // When we use `SuperClass[] list;` here, we find 'a' is 
> hidden by the base class
>     Variant[] list;
>
>     // Attempting to append derived class instances to list
>     list ~= new DerivedClass(1.0f);
>     list ~= new OtherDerivedClass;
>
>     list[0].a;
>     list[0].to!(get!(list[0].type)).a.writeln;
> }
> ```

This works:

```d
void main() {
     Variant[] list;

     list ~= new DerivedClass(1.0f).Variant;
     list ~= new OtherDerivedClass().Variant;

     writeln(list[0].get!DerivedClass.a);
}
```

Parameters passed in !() need to be statically known, at 
compile-time, so `get!(list[0].type)` doesn't make sense with a 
runtime list.

If everything in the list is going to be a child of some class, 
then you don't need std.variant at all, you can just use OOP:

```d
import std.stdio : writeln;

class SuperClass {
     this() {
     }
}

class DerivedClass : SuperClass {
public:
     this(float a) {
         this.a = a;
     }
     float a;
}

class OtherDerivedClass : SuperClass {}
class YetAnotherDerivedClass : SuperClass {}

void main() {
     SuperClass[] list;

     list ~= cast(SuperClass) new DerivedClass(1.0f);
     list ~= cast(SuperClass) new OtherDerivedClass;
     list ~= cast(SuperClass) new YetAnotherDerivedClass;

     writeln((cast(DerivedClass) list[0]).a);

     foreach (obj; list) {
         if (auto deriv = cast(DerivedClass) obj) {
             writeln("I found a DerivedClass: ", deriv.a);
         } else if (cast(OtherDerivedClass) obj) {
             writeln("I found an OtherDerivedClass");
         } else {
             writeln("I found an unexpected child: ", obj);
         }
     }
}
```

output:

```
1
I found a DerivedClass: 1
I found an OtherDerivedClass
I found an unexpected child: variant.YetAnotherDerivedClass
```

Object casts like that are `null` when the cast is invalid.

If you don't necessarily have a superclass, but still do have a 
definite number of possible member types, you can use std.sumtype:

```d
import std.stdio : writeln;
import std.sumtype;

struct A { float a; }
struct B { }
struct C { }
alias Alpha = SumType!(A, B, C);

void main() {
     Alpha[] list;

     list ~= A(1.0f).Alpha;
     list ~= B().Alpha;
     list ~= C().Alpha;

     list[0].tryMatch!((A a) => writeln(a.a));

     foreach (obj; list) {
         obj.match!(
             (A a) => writeln("I found A(", a.a, ")"),
             (B _) => writeln("I found B"),
             (C _) => writeln("I found C"),
         );
     }
}
```

output:

```
1
I found A(1)
I found B
I found C
```


More information about the Digitalmars-d-learn mailing list