Jump to page: 1 2 3
Thread overview
What's wrong with std.variant.Variant?
Jun 13, 2020
user1234
Jun 13, 2020
Johannes Pfau
Jun 13, 2020
welkam
Jun 13, 2020
Paul Backus
Jun 14, 2020
Mathias LANG
Jun 14, 2020
Dukc
Jun 14, 2020
Paul Backus
Jun 15, 2020
Dukc
Re: Tagged unions [Was: What's wrong with std.variant.Variant?]
Jun 15, 2020
Paul Backus
Jun 15, 2020
Dukc
Jun 15, 2020
Paul Backus
Jun 15, 2020
Dukc
Jun 16, 2020
Paul Backus
Jun 16, 2020
Simen Kjærås
Jun 16, 2020
Stanislav Blinov
Jun 16, 2020
Paul Backus
Jun 16, 2020
Dukc
Jun 16, 2020
Dukc
Jun 16, 2020
Dukc
Jun 16, 2020
Dukc
Jun 16, 2020
Paul Backus
Jun 15, 2020
Paolo Invernizzi
Jun 15, 2020
Justin Whear
Jun 15, 2020
Guillaume Piolat
June 13, 2020
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
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
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
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
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
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
On Saturday, 13 June 2020 at 19:51:51 UTC, Andrei Alexandrescu wrote:
> should eat more than 2 bytes.
He he
June 14, 2020
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
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
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);
« First   ‹ Prev
1 2 3