digitalmars.D.learn - Nesting Variants
- Wyatt (35/35) May 19 2013 I'm trying to use Variants and ran into the following sort of
- evilrat (9/44) May 20 2013 yes, you forgot to take exact value, it doesn't know anything
- Wyatt (15/23) May 21 2013 I was trying to do this as a way to obtain a concise syntax for
- Timothee Cour (5/53) Jun 13 2013 I think I have a solution for you:
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
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
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
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
what about this class? https://bitbucket.org/szabo_bogdan/cmsushid/raw/e2e4d2195bf48df586887768d2d800d21227c80d/src/base/Value.d
May 22 2013
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