Thread overview | ||||||||||||||||||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
June 13, 2020 What's wrong with std.variant.Variant? | ||||
---|---|---|---|---|
| ||||
I was curious about collecting a list of grievances about Variant. It's the oldest piece of generic code in std, and it predates a lot of good language additions. So what's wrong with Variant? One thing I collected from a coworker is that it doesn't work with Windows DLLs, because in turn typeof() comparison does not work across Windows DLLs. What are other problems with it? |
June 13, 2020 Re: What's wrong with std.variant.Variant? | ||||
---|---|---|---|---|
| ||||
Posted in reply to Andrei Alexandrescu | On Saturday, 13 June 2020 at 19:10:04 UTC, Andrei Alexandrescu wrote:
> I was curious about collecting a list of grievances about Variant. It's the oldest piece of generic code in std, and it predates a lot of good language additions.
>
> So what's wrong with Variant? One thing I collected from a coworker is that it doesn't work with Windows DLLs, because in turn typeof() comparison does not work across Windows DLLs.
>
> What are other problems with it?
IIRC another is the use of typeid() instead of an enum to discriminate the store
|
June 13, 2020 Re: What's wrong with std.variant.Variant? | ||||
---|---|---|---|---|
| ||||
Posted in reply to Andrei Alexandrescu | Am Sat, 13 Jun 2020 15:10:04 -0400 schrieb Andrei Alexandrescu: > So what's wrong with Variant? One thing I collected from a coworker is that it doesn't work with Windows DLLs, because in turn typeof() comparison does not work across Windows DLLs. I think you mean typeid? This is not Variant's fault though, we really need full DLL support in general... > What are other problems with it? I never had any real problems with std.variant, but I have some smaller nits: * Does the Algebraic implementation use typeid/TypeInfo? I think that's not documented and I'd prefer a numeric/enum tag * Memory Management is not documented Algebraic has to compete with https://code.dlang.org/packages/ taggedalgebraic which has some more features. I never really liked the Agelbraic APIs (phobos and TaggedAlgebraic: casting to get values / explicit get calls etc.). I prefer something with a union-like interface like TaggedUnion: union Base { int a; string b; } alias Type = TaggedUnion!Base; Type t = Type(0); t.a = 42; t.b = "foo"; writeln(t.b); if (t.kind == Type.Kind.Foo) if (t.isFoo)... -- Johannes |
June 13, 2020 Re: What's wrong with std.variant.Variant? | ||||
---|---|---|---|---|
| ||||
Posted in reply to user1234 | On 6/13/20 3:38 PM, user1234 wrote:
> On Saturday, 13 June 2020 at 19:10:04 UTC, Andrei Alexandrescu wrote:
>> I was curious about collecting a list of grievances about Variant. It's the oldest piece of generic code in std, and it predates a lot of good language additions.
>>
>> So what's wrong with Variant? One thing I collected from a coworker is that it doesn't work with Windows DLLs, because in turn typeof() comparison does not work across Windows DLLs.
>>
>> What are other problems with it?
>
> IIRC another is the use of typeid() instead of an enum to discriminate the store
It can't use an enum because it's open-ended (must accommodate any type). An enum would work for Algebraic but to consolidate implementations both use the same mechanism.
|
June 13, 2020 Re: What's wrong with std.variant.Variant? | ||||
---|---|---|---|---|
| ||||
Posted in reply to Johannes Pfau | On 6/13/20 3:42 PM, Johannes Pfau wrote: > Am Sat, 13 Jun 2020 15:10:04 -0400 schrieb Andrei Alexandrescu: > > >> So what's wrong with Variant? One thing I collected from a coworker is >> that it doesn't work with Windows DLLs, because in turn typeof() >> comparison does not work across Windows DLLs. > > I think you mean typeid? This is not Variant's fault though, we really > need full DLL support in general... Yes, typeid, thanks. >> What are other problems with it? > > I never had any real problems with std.variant, but I have some smaller > nits: > > * Does the Algebraic implementation use typeid/TypeInfo? I think that's > not documented and I'd prefer a numeric/enum tag I think so. It was just for the sake of reusing the same codebase for Algebraic and Variant. An enum might save space in some instances, but in most cases it simply eats a word anyway. But, space is important so this should go on the list. E.g. there should be no reason Algebraic!(char, byte, ubyte) should eat more than 2 bytes. > * Memory Management is not documented Yah, that whole thing with dynamic allocation and eager copying of types greater than a threshold. > Algebraic has to compete with https://code.dlang.org/packages/ > taggedalgebraic which has some more features. I never really liked the > Agelbraic APIs (phobos and TaggedAlgebraic: casting to get values / > explicit get calls etc.). I prefer something with a union-like interface > like TaggedUnion: > > union Base > { > int a; > string b; > } > > alias Type = TaggedUnion!Base; > > Type t = Type(0); > t.a = 42; > t.b = "foo"; > writeln(t.b); > if (t.kind == Type.Kind.Foo) > if (t.isFoo)... Interesting, so members should receive names much like they do in std.tuple. Cool. I think this could be done. Andrei |
June 13, 2020 Re: What's wrong with std.variant.Variant? | ||||
---|---|---|---|---|
| ||||
Posted in reply to Andrei Alexandrescu | On Saturday, 13 June 2020 at 19:10:04 UTC, Andrei Alexandrescu wrote: > I was curious about collecting a list of grievances about Variant. It's the oldest piece of generic code in std, and it predates a lot of good language additions. > > So what's wrong with Variant? One thing I collected from a coworker is that it doesn't work with Windows DLLs, because in turn typeof() comparison does not work across Windows DLLs. > > What are other problems with it? Here's what I found searching for "variant" on bugzilla: https://issues.dlang.org/show_bug.cgi?id=10223 https://issues.dlang.org/show_bug.cgi?id=12944 https://issues.dlang.org/show_bug.cgi?id=11864 https://issues.dlang.org/show_bug.cgi?id=12997 https://issues.dlang.org/show_bug.cgi?id=14062 https://issues.dlang.org/show_bug.cgi?id=15615 https://issues.dlang.org/show_bug.cgi?id=18780 https://issues.dlang.org/show_bug.cgi?id=18339 https://issues.dlang.org/show_bug.cgi?id=18183 https://issues.dlang.org/show_bug.cgi?id=20793 https://issues.dlang.org/show_bug.cgi?id=20666 https://issues.dlang.org/show_bug.cgi?id=20360 https://issues.dlang.org/show_bug.cgi?id=20030 Common themes: - issues with type conversions (esp. regarding const) - doesn't work with D's static analysis features (@safe, pure, etc.) - incorrect behavior for large types that require boxing |
June 13, 2020 Re: What's wrong with std.variant.Variant? | ||||
---|---|---|---|---|
| ||||
Posted in reply to Andrei Alexandrescu | On Saturday, 13 June 2020 at 19:51:51 UTC, Andrei Alexandrescu wrote:
> should eat more than 2 bytes.
He he
|
June 14, 2020 Re: What's wrong with std.variant.Variant? | ||||
---|---|---|---|---|
| ||||
Posted in reply to Andrei Alexandrescu | On Saturday, 13 June 2020 at 19:10:04 UTC, Andrei Alexandrescu wrote: > I was curious about collecting a list of grievances about Variant. It's the oldest piece of generic code in std, and it predates a lot of good language additions. > > So what's wrong with Variant? One thing I collected from a coworker is that it doesn't work with Windows DLLs, because in turn typeof() comparison does not work across Windows DLLs. > > What are other problems with it? I tried to use it a while ago and figured rolling out my own would be better (https://github.com/Geod24/minivariant). I've seen other (and probably better) implementations out there, but I mostly use this one because I'm familiar with the tradeoff. I think most people want a tagged union over a generic variant type, however things are built the other way around: the tagged union is built on the generic variant type. Building a typed union over a type that relies on type erasure means Algebraic has to reimplement all the conversions rules that would normally be done by the compiler, e.g. assigning `immutable(uint)` to a `ulong` should just work, but it does not. |
June 14, 2020 Re: What's wrong with std.variant.Variant? | ||||
---|---|---|---|---|
| ||||
Posted in reply to Andrei Alexandrescu | On Saturday, 13 June 2020 at 19:10:04 UTC, Andrei Alexandrescu wrote:
> So what's wrong with Variant? One thing I collected from a coworker is that it doesn't work with Windows DLLs, because in turn typeof() comparison does not work across Windows DLLs.
>
> What are other problems with it?
I have used both `std.variant` and DUB package Taggedalgebraic in a real project, so I think I can testify.
There is nothing absolutely wrong about Phobos variant -it is definitely an improvement over `union`s or `void[someSize]` in the general case. If I wanted to make a variant without pre-specifying the types, I'd still consider it (through I'd most likely check the Tardy library Atila just announced first).
But all my use cases have been ones where I can pre-provide a list. The typical thing I want to do is to either return a normal value or an error value. I personally don't like exceptions because I want to give the calling code an option to treat errors as normal low-level results without performance implications.
For that use, `std.variant` proved itself serviceable, but not optimal. The first problem is that it always has one separate `null` value. I want to be able to specify an arbitrary number of different null values, or to have none at all. `taggedalgebraic.TaggedUnion` lets me do this, with the `Void` type provided by the package.
The second problem is that standard variant will not work with any of the attributes. `TaggedUnion` neither works with `nothrow` or `@nogc`, but at least it has no problems with `@safe` and `pure`. The latter two are more important anyway.
And finally, with `TaggedUnion` the union can contain the same type two times, being still separate by it's tag value. If I want a tagged version of this:
```
union PictureSize
{ int[2] inPixels;
float[2] inMeters;
float[2] inSourceSizes;
}
```
...I can't do that with the standard variant.
|
June 14, 2020 Re: What's wrong with std.variant.Variant? | ||||
---|---|---|---|---|
| ||||
Posted in reply to Dukc | On Sunday, 14 June 2020 at 17:31:32 UTC, Dukc wrote:
> The second problem is that standard variant will not work with any of the attributes. `TaggedUnion` neither works with `nothrow` or `@nogc`, but at least it has no problems with `@safe` and `pure`. The latter two are more important anyway.
FYI, SumType works with nothrow and @nogc, and can solve all of your other problems with std.variant as well. :)
Duplicate types are not supported out-of-the-box, but can very easily be accomplished using `std.typecons.Typedef`:
alias InPixels = Typedef!(int[2], int[2].init, "InPixels");
alias InMeters = Typedef!(float[2], float[2].init, "InMeters");
alias SourceSizes = Typedef!(float[2], float[2].init, "SourceSizes");
alias PictureSize = SumType!(InPixels, InMeters, SourceSizes);
|
Copyright © 1999-2021 by the D Language Foundation