Thread overview
Algebraic changing type when in associative array
Feb 04, 2020
rous
Feb 04, 2020
rikki cattermole
Feb 04, 2020
rous
Feb 04, 2020
rikki cattermole
Feb 05, 2020
rous
Feb 05, 2020
Paul Backus
Feb 04, 2020
Paul Backus
Feb 04, 2020
rikki cattermole
February 04, 2020
I'm defining an Algebraic type like this:
alias Expr = Algebraic!(This[char], string, int);
However, when I create an Expr from an associative array of chars and Exprs, the Exprs seem to change from Algebraic to VariantN!32LU types. This is illustrated in the following error message:
cannot pass argument ex.opIndex(' ') of type VariantN!32LU to parameter VariantN!(16LU, This[char], string, int) ex
when I try to call a function that takes an Expr with ex[' '].
If there is no way to ensure that it does not change type, is there a way to cast it back?
February 05, 2020
It did not change type.

"Algebraic data type restricted to a closed set of possible types. It's an alias for VariantN with an appropriately-constructed maximum size."

https://dlang.org/phobos/std_variant.html#.Algebraic
February 04, 2020
On Tuesday, 4 February 2020 at 11:47:49 UTC, rikki cattermole wrote:
> It did not change type.
>
> "Algebraic data type restricted to a closed set of possible types. It's an alias for VariantN with an appropriately-constructed maximum size."
>
> https://dlang.org/phobos/std_variant.html#.Algebraic

Okay, that makes sense. However, shouldn't it still be the same Algebraic type, and thus an alias for a VariantN with the same maximum size?
February 05, 2020
On 05/02/2020 12:55 AM, rous wrote:
> On Tuesday, 4 February 2020 at 11:47:49 UTC, rikki cattermole wrote:
>> It did not change type.
>>
>> "Algebraic data type restricted to a closed set of possible types. It's an alias for VariantN with an appropriately-constructed maximum size."
>>
>> https://dlang.org/phobos/std_variant.html#.Algebraic
> 
> Okay, that makes sense. However, shouldn't it still be the same Algebraic type, and thus an alias for a VariantN with the same maximum size?

Algebraic doesn't exist. Its a name for your use.

This is what an alias is. It does not create a new type, it gives a name to another one.

This chapter of the book (free) goes into more detail about alias http://ddili.org/ders/d.en/alias.html
February 04, 2020
On Tuesday, 4 February 2020 at 11:45:50 UTC, rous wrote:
> I'm defining an Algebraic type like this:
> alias Expr = Algebraic!(This[char], string, int);
> However, when I create an Expr from an associative array of chars and Exprs, the Exprs seem to change from Algebraic to VariantN!32LU types. This is illustrated in the following error message:
> cannot pass argument ex.opIndex(' ') of type VariantN!32LU to parameter VariantN!(16LU, This[char], string, int) ex
> when I try to call a function that takes an Expr with ex[' '].
> If there is no way to ensure that it does not change type, is there a way to cast it back?

Can you post an example program that illustrates the error? You shouldn't be getting two different sizes (16 and 32) for the same Algebraic type.
February 05, 2020
On 05/02/2020 2:11 AM, Paul Backus wrote:
> On Tuesday, 4 February 2020 at 11:45:50 UTC, rous wrote:
>> I'm defining an Algebraic type like this:
>> alias Expr = Algebraic!(This[char], string, int);
>> However, when I create an Expr from an associative array of chars and Exprs, the Exprs seem to change from Algebraic to VariantN!32LU types. This is illustrated in the following error message:
>> cannot pass argument ex.opIndex(' ') of type VariantN!32LU to parameter VariantN!(16LU, This[char], string, int) ex
>> when I try to call a function that takes an Expr with ex[' '].
>> If there is no way to ensure that it does not change type, is there a way to cast it back?
> 
> Can you post an example program that illustrates the error? You shouldn't be getting two different sizes (16 and 32) for the same Algebraic type.

I missed this when I commented previously as there is two questions in the original post. My bad rous!
February 05, 2020
On Tuesday, 4 February 2020 at 12:05:16 UTC, rikki cattermole wrote:
> On 05/02/2020 12:55 AM, rous wrote:
>> On Tuesday, 4 February 2020 at 11:47:49 UTC, rikki cattermole wrote:
>>> It did not change type.
>>>
>>> "Algebraic data type restricted to a closed set of possible types. It's an alias for VariantN with an appropriately-constructed maximum size."
>>>
>>> https://dlang.org/phobos/std_variant.html#.Algebraic
>> 
>> Okay, that makes sense. However, shouldn't it still be the same Algebraic type, and thus an alias for a VariantN with the same maximum size?
>
> Algebraic doesn't exist. Its a name for your use.
>
> This is what an alias is. It does not create a new type, it gives a name to another one.
>
> This chapter of the book (free) goes into more detail about alias http://ddili.org/ders/d.en/alias.html

This is an example program that illustrates the issue:

import std.variant: Algebraic, This;
import std.stdio: writeln;
alias Foo = Algebraic!(This[], int);
void main()
{
    Foo x = 5;
    Foo y = 10;
    Foo z = [x,y];
    pragma(msg, typeof(x));
    pragma(msg, typeof(y));
    pragma(msg, typeof(z));
    pragma(msg, typeof(z[0]));
}
At compile time, it prints VariantN!(16LU, This[], int) three times and then VariantN!32LU.
February 05, 2020
On Wednesday, 5 February 2020 at 01:06:46 UTC, rous wrote:
> This is an example program that illustrates the issue:
>
> import std.variant: Algebraic, This;
> import std.stdio: writeln;
> alias Foo = Algebraic!(This[], int);
> void main()
> {
>     Foo x = 5;
>     Foo y = 10;
>     Foo z = [x,y];
>     pragma(msg, typeof(x));
>     pragma(msg, typeof(y));
>     pragma(msg, typeof(z));
>     pragma(msg, typeof(z[0]));
> }
> At compile time, it prints VariantN!(16LU, This[], int) three times and then VariantN!32LU.

The problem is that you are indexing directly into the Algebraic, using VariantN.opIndex [1], which returns a generic, non-Algebraic Variant. Instead, you should use visit [2] or tryVisit [3] to access the array contained inside the Algebraic, and index into that.

For example:

auto w = z.tryVisit!((Foo[] arr) => arr[0]);
static assert(is(typeof(w) == Foo));

[1] https://dlang.org/phobos/std_variant.html#.VariantN.opIndex
[2] https://dlang.org/phobos/std_variant.html#.visit
[3] https://dlang.org/phobos/std_variant.html#.tryVisit