www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - Nesting Variants

reply "Wyatt" <wyatt.epp gmail.com> writes:
I'm trying to use Variants and ran into the following sort of 
situation:

//Using DMD 2.062
import std.stdio;
import std.variant;

void main(){
	int key = 1;
	Variant[] one;
	Variant[] ender;
	one = new Variant[](1);
	ender = new Variant[](1);

	//This bails:
	//std.variant.VariantException std/variant.d(1224): Variant: 
attempting to use incompatible types int and 
std.variant.VariantN!(32LU).VariantN
	ender[0] = one;
	ender[0][0] = key;
	writeln(ender[0][0]);

	//Also bails only rather than int, it's 
std.variant.VariantN!(32LU).VariantN*:	
	//ender[0][0] = new Variant(key);

	//This works fine:
	//one[0] = key;
	//ender[0] = one;
	//writeln(ender[0][0]);
}

The long and short of it seems to be that you can't (easily) 
assign to an element of a Variant array within a Variant array 
but you CAN access it as long as you build the whole thing 
upside-down.  Can anyone shed some light on why this is?  Am I 
just missing some not-completely-obvious step?

Oh, I should probably mention I was originally using associative 
arrays, so I thought maybe I'd hit one of the bugs related to 
that. But as you can see, it's happening even with ordinary 
arrays.
May 19 2013
next sibling parent reply "evilrat" <evilrat666 gmail.com> writes:
On Sunday, 19 May 2013 at 23:31:11 UTC, Wyatt wrote:
 I'm trying to use Variants and ran into the following sort of 
 situation:

 //Using DMD 2.062
 import std.stdio;
 import std.variant;

 void main(){
 	int key = 1;
 	Variant[] one;
 	Variant[] ender;
 	one = new Variant[](1);
 	ender = new Variant[](1);

 	//This bails:
 	//std.variant.VariantException std/variant.d(1224): Variant: 
 attempting to use incompatible types int and 
 std.variant.VariantN!(32LU).VariantN
 	ender[0] = one;
 	ender[0][0] = key;
 	writeln(ender[0][0]);

 	//Also bails only rather than int, it's 
 std.variant.VariantN!(32LU).VariantN*:	
 	//ender[0][0] = new Variant(key);

 	//This works fine:
 	//one[0] = key;
 	//ender[0] = one;
 	//writeln(ender[0][0]);
 }

 The long and short of it seems to be that you can't (easily) 
 assign to an element of a Variant array within a Variant array 
 but you CAN access it as long as you build the whole thing 
 upside-down.  Can anyone shed some light on why this is?  Am I 
 just missing some not-completely-obvious step?

 Oh, I should probably mention I was originally using 
 associative arrays, so I thought maybe I'd hit one of the bugs 
 related to that. But as you can see, it's happening even with 
 ordinary arrays.
yes, you forgot to take exact value, it doesn't know anything about array you put it in, so if you take that array explicitly and put value on array element it would work ender[0] = one; ender[0].get!(Variant[])[0] = key; writeln(ender[0][0]); // writes 1 also you can check whats inside by doing just this "writeln(ender);" in case you are not sure what's going on.
May 20 2013
parent reply "Wyatt" <wyatt.epp gmail.com> writes:
On Monday, 20 May 2013 at 08:55:24 UTC, evilrat wrote:
 yes, you forgot to take exact value, it doesn't know anything 
 about array you put it in, so if you take that array explicitly 
 and put value on array element it would work

 ender[0] = one;
 ender[0].get!(Variant[])[0] = key;
 writeln(ender[0][0]); // writes 1

 also you can check whats inside by doing just this 
 "writeln(ender);" in case you are not sure what's going on.
I was trying to do this as a way to obtain a concise syntax for manipulating a tree of elements deserialized at runtime, ex: data["foo"]["bar"] = "baz"; assert( data["foo"]["bar"] == "baz" ); foreach( subtree; data["foo"] ) doSubtreeOp( subtree ); Having to place .get!(Variant[]) between each dereference will defeat my use case. Associative arrays fail in the same way, btw. I'm using integers in the first example because it should be simpler to get those right. I expected this to work because the value of 'ender[0]' will be a variant that contains an array, and such a variant should be able to index the contained array because of its opIndex overload.
May 21 2013
next sibling parent "evilrat" <evilrat666 gmail.com> writes:
On Wednesday, 22 May 2013 at 01:04:35 UTC, Wyatt wrote:
 I was trying to do this as a way to obtain a concise syntax for 
 manipulating a tree of elements deserialized at runtime, ex:
 data["foo"]["bar"] = "baz";
 assert( data["foo"]["bar"] == "baz" );
 foreach( subtree; data["foo"] )
     doSubtreeOp( subtree );

 Having to place .get!(Variant[]) between each dereference will 
 defeat my use case.

 Associative arrays fail in the same way, btw.  I'm using 
 integers in the first example because it should be simpler to 
 get those right.

 I expected this to work because the value of 'ender[0]' will be 
 a variant that contains an array, and such a variant should be 
 able to index the contained array because of its opIndex 
 overload.
if this is a tree anyway better use custom node types. so why not do this and overload opindex? unlike c++ u can put anything as key. i can't say from this example what types you are going to use but if it's only strings this should be very easy to implement.
May 21 2013
prev sibling parent "gedaiu" <szabobogdan yahoo.com> writes:
what about this class?

https://bitbucket.org/szabo_bogdan/cmsushid/raw/e2e4d2195bf48df586887768d2d800d21227c80d/src/base/Value.d
May 22 2013
prev sibling parent Timothee Cour <thelastmammoth gmail.com> writes:
On Sun, May 19, 2013 at 4:31 PM, Wyatt <wyatt.epp gmail.com> wrote:

 I'm trying to use Variants and ran into the following sort of situation:

 //Using DMD 2.062
 import std.stdio;
 import std.variant;

 void main(){
         int key = 1;
         Variant[] one;
         Variant[] ender;
         one = new Variant[](1);
         ender = new Variant[](1);

         //This bails:
         //std.variant.**VariantException std/variant.**d(1224): Variant:
 attempting to use incompatible types int and std.variant.VariantN!(32LU).*
 *VariantN
         ender[0] = one;
         ender[0][0] = key;
         writeln(ender[0][0]);

         //Also bails only rather than int, it's
 std.variant.VariantN!(32LU).**VariantN*:
         //ender[0][0] = new Variant(key);

         //This works fine:
         //one[0] = key;
         //ender[0] = one;
         //writeln(ender[0][0]);
 }

 The long and short of it seems to be that you can't (easily) assign to an
 element of a Variant array within a Variant array but you CAN access it as
 long as you build the whole thing upside-down.  Can anyone shed some light
 on why this is?  Am I just missing some not-completely-obvious step?

 Oh, I should probably mention I was originally using associative arrays,
 so I thought maybe I'd hit one of the bugs related to that. But as you can
 see, it's happening even with ordinary arrays.
I think I have a solution for you: see thread: http://forum.dlang.org/post/mailman.1054.1371029915.13711.digitalmars-d puremagic.com <https://github.com/timotheecour/dtools/blob/master/dtools/util/variant_nested.d>
 https://github.com/timotheecour/dtools/blob/master/dtools/util/variant_nested.d
        auto
 d=variantTupleNamed("a",1,"b","foo","c",variantTuple(1,2.2,"three"));
 d["a"]=2;
 auto v=d["c"][0].get!int;//can coerce to int
 v+=3;
 d["c"][0]="other1";//can access nested type
 d["a"]="other2";//can change type
 d["a"]=variantTuple(0.0,'e');
 d["a"]=10;
 d["a"]+=2; //read-modify-write works, unlike std.variant : 'Due to
 limitations in current language, read-modify-write operations op= will not
 work properly'
 assert(d.text==`["a":12, "b":foo, "c":[other1, 2.2, three]]`);
 Pending DIP32 (Uniform tuple syntax), this could improve to:
        auto d=variant( {a=1,b="foo", c={1,2.2,"three"}} );
Jun 13 2013