Jump to page: 1 2
Thread overview
variant visit not pure?
May 07, 2020
learner
May 07, 2020
Dukc
May 08, 2020
Dukc
May 07, 2020
Simen Kjærås
May 07, 2020
learner
May 07, 2020
Dukc
May 07, 2020
Ben Jones
May 07, 2020
Paul Backus
May 08, 2020
Dukc
May 07, 2020
learner
May 08, 2020
Dukc
May 07, 2020
Good morning,

Is there a reason why std.variant.visit is not inferring pure?

```
void test() pure {
    Algebraic!(int, string) alg;
    visit!( (string) => 0, (int) => 0)(alg);
}

Error: pure function test cannot call impure function test.visit!(VariantN!(16LU, int, string)).visit
```

Thank you
May 07, 2020
On Thursday, 7 May 2020 at 09:22:28 UTC, learner wrote:
> Good morning,
>
> Is there a reason why std.variant.visit is not inferring pure?
>

I think `variant` will not infer any trributes. I'm not sure why. It could be some language limitation (that's the reason why `std.range.enumerate` does not infer attributes for example). Or it could be just badly implemented.

Either way, there are DUB packages that are better in this (and other) regards. I recommend Taggedalgebraic[1].

[1] https://code.dlang.org/packages/taggedalgebraic

May 07, 2020
On Thursday, 7 May 2020 at 09:22:28 UTC, learner wrote:
> Good morning,
>
> Is there a reason why std.variant.visit is not inferring pure?
>
> ```
> void test() pure {
>     Algebraic!(int, string) alg;
>     visit!( (string) => 0, (int) => 0)(alg);
> }
>
> Error: pure function test cannot call impure function test.visit!(VariantN!(16LU, int, string)).visit
> ```

std.variant.Algebraic is essentially a std.variant.Variant in different clothes. Variant is very flexible, and this comes at a cost (and isn't used in Algebraic, meaning you pay for things you don't use). Like Dukc said, you might be better off with Taggedalgebraic or SumType (https://code.dlang.org/packages/sumtype).


Variant uses runtime type information to hold *any* type. Since Algebraic specifically only holds a few types, all the framework that's in place for Variant is wasted on Algebraic, and makes it less useful and less performant.

--
  Simen
May 07, 2020
On Thursday, 7 May 2020 at 10:41:01 UTC, Simen Kjærås wrote:
> On Thursday, 7 May 2020 at 09:22:28 UTC, learner wrote:
>> Good morning,
>>
>> Is there a reason why std.variant.visit is not inferring pure?
>>
>> ```
>> void test() pure {
>>     Algebraic!(int, string) alg;
>>     visit!( (string) => 0, (int) => 0)(alg);
>> }
>>
>> Error: pure function test cannot call impure function test.visit!(VariantN!(16LU, int, string)).visit
>> ```
>
> std.variant.Algebraic is essentially a std.variant.Variant in different clothes. Variant is very flexible, and this comes at a cost (and isn't used in Algebraic, meaning you pay for things you don't use). Like Dukc said, you might be better off with Taggedalgebraic or SumType (https://code.dlang.org/packages/sumtype).
>
>
> Variant uses runtime type information to hold *any* type. Since Algebraic specifically only holds a few types, all the framework that's in place for Variant is wasted on Algebraic, and makes it less useful and less performant.
>
> --
>   Simen

Thank you Simon and Dukc,

I've find this: https://issues.dlang.org/show_bug.cgi?id=16662

So, it seems that Phobos isn't in a good shape ... what a pity!
May 07, 2020
On Thursday, 7 May 2020 at 13:17:21 UTC, learner wrote:
> I've find this: https://issues.dlang.org/show_bug.cgi?id=16662

Hmm, that explains why it can't infer attributes. An unlimited variant could contain an object, and using it might or might not be <insert attribute here>.

Of course, it could still infer the attribute for algebraic types were the wrapper a bit smarter. But `Algebraic` is inferior to the DUB packages anyway. Bad performance like Simen said, and can always be `null` regardless of requested types. With Taggedalgebraic, you can insert `Void` to allowed types if you want `null` value but you don't have it just because.
May 07, 2020
On 5/7/20 5:22 AM, learner wrote:
> Good morning,
> 
> Is there a reason why std.variant.visit is not inferring pure?
> 
> ```
> void test() pure {
>      Algebraic!(int, string) alg;
>      visit!( (string) => 0, (int) => 0)(alg);
> }
> 
> Error: pure function test cannot call impure function test.visit!(VariantN!(16LU, int, string)).visit
> ```
> 
> Thank you

Because VariantN (the base of Algebraic) can literally hold anything, it cannot be pure, @safe, nothrow, @nogc.

As others have recommended, I suggest using TaggedAlgebraic. I recently have been using it to create an algebraic type to hold a MYSQL value, so I can migrate the mysql-native library to be @safe (mysql-native currently uses Variant for everything).

I added a special UDA to TaggedAlgebraic, so you can guarantee only @safe calls are allowed (for instance, if it can hold a pointer and an int, then opBinary!"+" can be marked as @safe if the operation fails when it's a pointer).

TaggedAlgebraic could probably do the same for pure, but not sure about nothrow and @nogc, since it uses exceptions when things aren't valid.

-Steve
May 07, 2020
On Thursday, 7 May 2020 at 14:53:10 UTC, Steven Schveighoffer wrote:

> As others have recommended, I suggest using TaggedAlgebraic. I recently have been using it to create an algebraic type to hold a MYSQL value, so I can migrate the mysql-native library to be @safe (mysql-native currently uses Variant for everything).
>
> -Steve

I've been using SumType... What are the main differences between it and TaggedAlgebraic?


May 07, 2020
On Thursday, 7 May 2020 at 15:36:36 UTC, Ben Jones wrote:
> On Thursday, 7 May 2020 at 14:53:10 UTC, Steven Schveighoffer wrote:
>
>> As others have recommended, I suggest using TaggedAlgebraic. I recently have been using it to create an algebraic type to hold a MYSQL value, so I can migrate the mysql-native library to be @safe (mysql-native currently uses Variant for everything).
>>
>> -Steve
>
> I've been using SumType... What are the main differences between it and TaggedAlgebraic?

As far as I can tell, there are two main differences:

1. TaggedAlgebraic has some convenient operator overloads that can assert at runtime if called improperly (i.e., when the contained type does not support the operation). SumType never asserts at runtime, and instead requires you to use `match` for these operations to ensure that they are only performed on the appropriate types.

2. TaggedAlgebraic requires you to declare a union type as a "base", whereas SumType takes the list of member types directly as template arguments.

If you want more detailed information, both have online documentation:

TaggedAlgebraic: https://vibed.org/api/taggedalgebraic.taggedalgebraic/
SumType: https://pbackus.github.io/sumtype/sumtype.html
May 07, 2020
On Thursday, 7 May 2020 at 14:53:10 UTC, Steven Schveighoffer wrote:
> On 5/7/20 5:22 AM, learner wrote:
>> [...]
>
> Because VariantN (the base of Algebraic) can literally hold anything, it cannot be pure, @safe, nothrow, @nogc.
>
> As others have recommended, I suggest using TaggedAlgebraic. I recently have been using it to create an algebraic type to hold a MYSQL value, so I can migrate the mysql-native library to be @safe (mysql-native currently uses Variant for everything).
>
> I added a special UDA to TaggedAlgebraic, so you can guarantee only @safe calls are allowed (for instance, if it can hold a pointer and an int, then opBinary!"+" can be marked as @safe if the operation fails when it's a pointer).
>
> TaggedAlgebraic could probably do the same for pure, but not sure about nothrow and @nogc, since it uses exceptions when things aren't valid.
>
> -Steve

Modules of D standard library aren't in a good shape, if everyone suggests alternatives for a basic building block as variant.

The types VariantN can hold are known at compile time, why can't it be specialized?


May 08, 2020
On Thursday, 7 May 2020 at 10:21:26 UTC, Dukc wrote:
>
> that's the reason why `std.range.enumerate` does not infer attributes for example

This was wrong. `enumerate` can infer. It's `lockstep` that cannot.


« First   ‹ Prev
1 2