www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - Variant associative arrays

reply Byron Heads <byron.heads gmail.com> writes:
I have a variant associative array.  In the example below I am wondering 
if there is a way to create the array without having to indicate the 
variant type on all of the values. Would like to be able to write code 
like #2, or something cleaner/better for #1.  This is intended for a 
library. Other option would be variable parameters, not sure how the 
function signature would look for this.

Any ideas, complaints?

import	std.stdio,
	std.variant;

alias Algebraic!(string, long) HDType;

void main()
{ 

	// #1 This works
	foo(["first" : HDType("John"), 
		"last" : HDType("Doe"), 
		"phone" : HDType(1234546)]);

	// #2 Wont compile, type mismatch string and long
	foo(["first" : "John", 
		"last" : "Doe", 
		"phone" : 1234546]);

	// #3 Other idea
	bar("first", "John", "last", "Doe", "phone", 12345678);	

}

void foo(HDType[string] attr)
{
	foreach(string k, ref HDType v; attr)
	{
		writeln(k, ". ", v.toString());
	}
}
May 08 2013
next sibling parent reply "bearophile" <bearophileHUGS lycos.com> writes:
Byron Heads:

 I have a variant associative array.  In the example below I am 
 wondering
 if there is a way to create the array without having to 
 indicate the
 variant type on all of the values. Would like to be able to 
 write code
 like #2, or something cleaner/better for #1.
 ...
 	// #1 This works
 	foo(["first" : HDType("John"),
 		"last" : HDType("Doe"),
 		"phone" : HDType(1234546)]);

 	// #2 Wont compile, type mismatch string and long
 	foo(["first" : "John",
 		"last" : "Doe",
 		"phone" : 1234546]);
If your purpose is to write such associative literal without repeating the HDType(), then a possibility is to write the data in a single string, and feed it to a compile-time function that splits it and builds the associative array. Bye, bearophile
May 08 2013
parent Byron Heads <byron.heads gmail.com> writes:
On Thu, 09 May 2013 02:33:08 +0200, bearophile wrote:

 Byron Heads:
 
 I have a variant associative array.  In the example below I am
 wondering if there is a way to create the array without having to
 indicate the variant type on all of the values. Would like to be able
 to write code like #2, or something cleaner/better for #1.
 ...
 	// #1 This works foo(["first" : HDType("John"),
 		"last" : HDType("Doe"), "phone" : HDType(1234546)]);

 	// #2 Wont compile, type mismatch string and long foo(["first" :
 	"John",
 		"last" : "Doe",
 		"phone" : 1234546]);
If your purpose is to write such associative literal without repeating the HDType(), then a possibility is to write the data in a single string, and feed it to a compile-time function that splits it and builds the associative array. Bye, bearophile
That approch may work. Will have to experiment with the API more.
May 09 2013
prev sibling parent reply "evilrat" <evilrat666 gmail.com> writes:
On Thursday, 9 May 2013 at 00:10:48 UTC, Byron Heads wrote:
 I have a variant associative array.  In the example below I am 
 wondering
 if there is a way to create the array without having to 
 indicate the
 variant type on all of the values. Would like to be able to 
 write code
 like #2, or something cleaner/better for #1.  This is intended 
 for a
 library. Other option would be variable parameters, not sure 
 how the
 function signature would look for this.

 Any ideas, complaints?

 import	std.stdio,
 	std.variant;

 alias Algebraic!(string, long) HDType;

 void main()
 {

 	// #1 This works
 	foo(["first" : HDType("John"),
 		"last" : HDType("Doe"),
 		"phone" : HDType(1234546)]);

 	// #2 Wont compile, type mismatch string and long
 	foo(["first" : "John",
 		"last" : "Doe",
 		"phone" : 1234546]);

 	// #3 Other idea
 	bar("first", "John", "last", "Doe", "phone", 12345678);	

 }

 void foo(HDType[string] attr)
 {
 	foreach(string k, ref HDType v; attr)
 	{
 		writeln(k, ". ", v.toString());
 	}
 }
first doesn't compile with DMD 2.062 as int implicitly not converted to long. foo func takes associative array, within this example you can use type Variant[string] to make life a bit easier(but i can't recommend it for ur real code cause we don't know the usage). and for third func here is example code, though it doesn't takes associative array you can rewrite it to suit ur needs, also notice that it's a bit dirty and not very readable cause i'm superlazy and quite in a hurry, so you can improve it yourself --------------- void bar(...) { import core.vararg; enum string handler = `.visit! ( // string type handler (string s) => write(s, pos %2 == 0 ? ':' : '\n'), // long type handler (long l) => write(l, pos %2 == 0 ? ':' : '\n') )();`; for( int pos = 0; pos < _arguments.length ; pos++ ) { if ( _arguments[pos] == typeid(HDType) ) mixin(`(va_arg!(HDType)(_argptr))` ~ handler ); else if ( _arguments[pos] == typeid(string) ) mixin(`HDType(va_arg!(string)(_argptr))` ~ handler ); else if ( _arguments[pos] == typeid(long) ) mixin(`HDType(va_arg!(long)(_argptr))` ~ handler ); else throw new Exception("wrong type"); } }
May 08 2013
parent Byron Heads <byron.heads gmail.com> writes:
On Thu, 09 May 2013 03:29:06 +0200, evilrat wrote:

 first doesn't compile with DMD 2.062 as int implicitly not converted to
 long.
 
 foo func takes associative array, within this example you can use type
 Variant[string] to make life a bit easier(but i can't recommend it for
 ur real code cause we don't know the usage).
 
 and for third func here is example code, though it doesn't takes
 associative array you can rewrite it to suit ur needs, also notice that
 it's a bit dirty and not very readable cause i'm superlazy and quite in
 a hurry, so you can improve it yourself
 
 ---------------
 
 void bar(...)
 {
 	import core.vararg;
 
 	enum string handler = `.visit! (
 		// string type handler (string s) => write(s, pos %2 == 
0 ? ':' :
 		'\n'),
 		// long type handler (long l) => write(l, pos %2 == 0 ? 
':' : '\n')
 		)();`;
 
 
 	for( int pos = 0; pos < _arguments.length ; pos++ )
 	{
 
 		if ( _arguments[pos] == typeid(HDType) )
 			mixin(`(va_arg!(HDType)(_argptr))` ~ handler );
 
 		else if ( _arguments[pos] == typeid(string) )
 			mixin(`HDType(va_arg!(string)(_argptr))` ~ 
handler );
 
 		else if ( _arguments[pos] == typeid(long) )
 			mixin(`HDType(va_arg!(long)(_argptr))` ~ handler 
);
 
 		else
 			throw new Exception("wrong type");
 	}
 }
I think I had a large const in there when I tested so it worked then. This gives me a few ideas, but I may try a different API.
May 09 2013