www.digitalmars.com         C & C++   DMDScript  

digitalmars.D - Typedef blocks

reply pragma <EricAnderton at yahoo dot com> <pragma_member pathlink.com> writes:
All apologies if this has been suggested before.

I think it would be useful to be able to extend basic types using typedef as an
optional block, with struct-like semantics inside.  

Take the following:



In order to organize access to this type I have to write several functions to
better encapsulate all the repeated bits that I use. 




The attribs would be set using the type's built-in array indexing.





I could write a class to emulate the char[char[]] type, and expose the needed
methods.  This seems like persisting a bad habit and an equally bad design as,
I'm just basically rewriting an existing type.  

What I'd like to be able to do is *extend* the existing type (char[][char[]]) by
adding some methods to it, which isn't possible because it's neither a struct
nor a class.

-- Proposal --

Ideally i'd like to be able to use a primitive as a base for a struct or a
class, but that won't work for a whole host of reasons.  Instead, I'd like to be
able to attach a scope to a typedef, which contains only static data and methods
that implicitly work against the base type.












This would allow AttributeSet, for example, to behave as a "char[][char[]]"
while having methods that are passed the instance implicitly via "this".  










By this, we have a set of methods that are intended to work with one primitive
type, and are scoped as such.  Yet we avoid the overhead of a class, and the
(laborious) rewriting of a primitive's capabilities in a class or struct.  

- Pragma
Aug 03 2004
next sibling parent Regan Heath <regan netwin.co.nz> writes:
Hows this...

import std.string;

class AttributeSetT(Value, Key)
{
	Value getAttribute(Key key)
	{
		return data[key];
	}
	
	Value getRequiredAttribute(Key key)
	{
		Value v = data[key];
		if (v == v.init) {
			char[] keyname;
			
			if (typeid(typeof(key)) === typeid(char[])) keyname = key;
			else keyname = std.string.toString(key);
			
			throw new Error(keyname ~ " is required.");
		}
		return v;
	}
	
	Value opIndex(Key key)
	{
		return data[key];
	}
	
	Value opIndexAssign(Value val, Key key)
	{
		data[key] = val;
		return data[key];
	}
	
private:
	Value[Key] data;
}

typedef AttributeSetT!(char[],char[]) Set1;
typedef AttributeSetT!(int,char[])    Set2;
typedef AttributeSetT!(float,int)     Set3;

void main()
{
	Set1 a1 = new Set1();
	char[] v1;
	
	Set2 a2 = new Set2();
	int v2;
	
	Set3 a3 = new Set3();
	float v3;
	
	
	printf("SET1 start\n");
	a1["a"] = "1";
	v1 = a1.getAttribute("a");
	printf("a is %.*s\n",v1);	
	try { v1 = a1.getRequiredAttribute("b");}
	catch(Error e) { e.print(); }	
	printf("SET1 done\n\n");
	
	printf("SET2 start\n");
	a2["a"] = 1;
	v2 = a2.getAttribute("a");
	printf("a is %d\n",v2);	
	try { v2 = a2.getRequiredAttribute("b");}
	catch(Error e) { e.print(); }	
	printf("SET2 done\n\n");

	printf("SET3 start\n");
	a3[1] = 2.0;
	v3 = a3.getAttribute(1);
	printf("1 is %f\n",v3);	
	try { v3 = a3.getRequiredAttribute(2);}
	catch(Error e) { e.print(); }	
	printf("SET3 done\n\n");
}

Regan

On Wed, 4 Aug 2004 01:47:17 +0000 (UTC), pragma <EricAnderton at yahoo dot 
com pragma_member pathlink.com> wrote:

 All apologies if this has been suggested before.

 I think it would be useful to be able to extend basic types using 
 typedef as an
 optional block, with struct-like semantics inside.

 Take the following:



 In order to organize access to this type I have to write several 
 functions to
 better encapsulate all the repeated bits that I use.




 The attribs would be set using the type's built-in array indexing.





 I could write a class to emulate the char[char[]] type, and expose the 
 needed
 methods.  This seems like persisting a bad habit and an equally bad 
 design as,
 I'm just basically rewriting an existing type.

 What I'd like to be able to do is *extend* the existing type 
 (char[][char[]]) by
 adding some methods to it, which isn't possible because it's neither a 
 struct
 nor a class.

 -- Proposal --

 Ideally i'd like to be able to use a primitive as a base for a struct or 
 a
 class, but that won't work for a whole host of reasons.  Instead, I'd 
 like to be
 able to attach a scope to a typedef, which contains only static data and 
 methods
 that implicitly work against the base type.












 This would allow AttributeSet, for example, to behave as a 
 "char[][char[]]"
 while having methods that are passed the instance implicitly via "this".










 By this, we have a set of methods that are intended to work with one 
 primitive
 type, and are scoped as such.  Yet we avoid the overhead of a class, and 
 the
 (laborious) rewriting of a primitive's capabilities in a class or struct.

 - Pragma
-- Using M2, Opera's revolutionary e-mail client: http://www.opera.com/m2/
Aug 03 2004
prev sibling parent reply "Ivan Senji" <ivan.senji public.srce.hr> writes:
I don't know if this helps:


typedef char[][char[]] AttributeSet;

char[] getAttribute(AttributeSet a, char[] x)
{
    //do something
}

void main ()
{
     AttributeSet set;
     set["name"] = "foo";
     set["color"] = "red";
     set.getAttribute("BLA");
}




"pragma" <EricAnderton at yahoo dot compragma_member pathlink.com> wrote in
message news:cepf75$1qi0$1 digitaldaemon.com...
 All apologies if this has been suggested before.

 I think it would be useful to be able to extend basic types using typedef
as an
 optional block, with struct-like semantics inside.

 Take the following:



 In order to organize access to this type I have to write several functions
to
 better encapsulate all the repeated bits that I use.




 The attribs would be set using the type's built-in array indexing.





 I could write a class to emulate the char[char[]] type, and expose the
needed
 methods.  This seems like persisting a bad habit and an equally bad design
as,
 I'm just basically rewriting an existing type.

 What I'd like to be able to do is *extend* the existing type
(char[][char[]]) by
 adding some methods to it, which isn't possible because it's neither a
struct
 nor a class.

 -- Proposal --

 Ideally i'd like to be able to use a primitive as a base for a struct or a
 class, but that won't work for a whole host of reasons.  Instead, I'd like
to be
 able to attach a scope to a typedef, which contains only static data and
methods
 that implicitly work against the base type.












 This would allow AttributeSet, for example, to behave as a
"char[][char[]]"
 while having methods that are passed the instance implicitly via "this".










 By this, we have a set of methods that are intended to work with one
primitive
 type, and are scoped as such.  Yet we avoid the overhead of a class, and
the
 (laborious) rewriting of a primitive's capabilities in a class or struct.

 - Pragma
Aug 04 2004
next sibling parent reply pragma <EricAnderton at yahoo dot com> <pragma_member pathlink.com> writes:
In article <ceq4g5$236p$1 digitaldaemon.com>, Ivan Senji says...
I don't know if this helps:


typedef char[][char[]] AttributeSet;

char[] getAttribute(AttributeSet a, char[] x)
{
    //do something
}

void main ()
{
     AttributeSet set;
     set["name"] = "foo";
     set["color"] = "red";
     set.getAttribute("BLA");
}
*stunned* Wow... I honestly didn't think that would work. So D implicitly passes the first arg if it's a match for the 'object' to the left? Nifty. This gets really close to the mark of my proposal. What it lacks is the kind of first class method-to-type grouping that classes and structs get. :) Regan also posted this beautiful template that does the job well. That's a good solution too, but it would require a developer to rewrite every facet that the primitive type already provides. Its the duplication of effort that I would love to see replaced since that is typically a Bad Thing(tm). Using your suggestion, I tried to (once again) create a multicast delegate (event). But of course we cannot override operators in the global scope, so /something/ is still needed. But it does work as long as you invoke using .opCall verbatim. - Pragma
Aug 04 2004
parent reply "Ivan Senji" <ivan.senji public.srce.hr> writes:
"pragma" <EricAnderton at yahoo dot compragma_member pathlink.com> wrote in
message news:ceqq0o$2oof$1 digitaldaemon.com...
 In article <ceq4g5$236p$1 digitaldaemon.com>, Ivan Senji says...
I don't know if this helps:


typedef char[][char[]] AttributeSet;

char[] getAttribute(AttributeSet a, char[] x)
{
    //do something
}

void main ()
{
     AttributeSet set;
     set["name"] = "foo";
     set["color"] = "red";
     set.getAttribute("BLA");
}
*stunned*
indeed!
 Wow... I honestly didn't think that would work.  So D implicitly passes
the
 first arg if it's a match for the 'object' to the left?  Nifty.  This gets
Only if the first arg is an array!
 really close to the mark of my proposal.  What it lacks is the kind of
first
 class method-to-type grouping that classes and structs get. :)
What about soemthing like this: template AttributeSet(T,V) { typedef T[V] AttributeSet; T getAttribute(AttributeSet a, V x) { writefln(x); return a[x]; } } void main () { mixin AttributeSet!(char[],char[]) AttributeSetX; AttributeSetX.AttributeSet set; set["name"] = "foo"; set["color"] = "red"; set.getAttribute("BLA"); }
 Regan also posted this beautiful template that does the job well.  That's
a good
 solution too, but it would require a developer to rewrite every facet that
the
 primitive type already provides.  Its the duplication of effort that I
would
 love to see replaced since that is typically a Bad Thing(tm).

 Using your suggestion, I tried to (once again) create a multicast delegate
 (event).










 But of course we cannot override operators in the global scope, so
/something/
 is still needed.  But it does work as long as you invoke using .opCall
verbatim. Or maby a class solution would be best?
 - Pragma
Aug 04 2004
parent reply pragma <EricAnderton at yahoo dot com> <pragma_member pathlink.com> writes:
In article <cequ4v$312p$1 digitaldaemon.com>, Ivan Senji says...
What about soemthing like this:

template AttributeSet(T,V)
{
     typedef T[V] AttributeSet;

     T getAttribute(AttributeSet a, V x)
     {
          writefln(x);
          return a[x];
     }
}

void main ()
{
 mixin AttributeSet!(char[],char[]) AttributeSetX;
 AttributeSetX.AttributeSet set;
 set["name"] = "foo";
 set["color"] = "red";
 set.getAttribute("BLA");
}
Or better yet: alias AttributeSet!(char[],char[]).AttributeSet ASet; Aset set; Which should make things a little more transparent, especially when passing it around from function to function.









 But of course we cannot override operators in the global scope, so
/something/
 is still needed.  But it does work as long as you invoke using .opCall
verbatim. Or maby a class solution would be best?
I'd agree, except in order to do the same /exact/ thing as my proposed typedef block, you're looking at reproducing the behavior in roughly 12 methods and members that are already available in char[char[]]. I know that using a class is the best way ahead for now, but extending typedef this way leads to much more maintainable code IMO. - Pragma
Aug 04 2004
parent "Ivan Senji" <ivan.senji public.srce.hr> writes:
"pragma" <EricAnderton at yahoo dot compragma_member pathlink.com> wrote in
message news:cer1f8$5kj$1 digitaldaemon.com...
 In article <cequ4v$312p$1 digitaldaemon.com>, Ivan Senji says...
What about soemthing like this:

template AttributeSet(T,V)
{
     typedef T[V] AttributeSet;

     T getAttribute(AttributeSet a, V x)
     {
          writefln(x);
          return a[x];
     }
}

void main ()
{
 mixin AttributeSet!(char[],char[]) AttributeSetX;
 AttributeSetX.AttributeSet set;
 set["name"] = "foo";
 set["color"] = "red";
 set.getAttribute("BLA");
}
Or better yet: alias AttributeSet!(char[],char[]).AttributeSet ASet; Aset set;
This is what i did at first too, but there wasn't a way to call set.getAttrubute in a simple way! Or have you found a way!
 Which should make things a little more transparent, especially when
passing it
 around from function to function.










 But of course we cannot override operators in the global scope, so
/something/
 is still needed.  But it does work as long as you invoke using .opCall
verbatim. Or maby a class solution would be best?
I'd agree, except in order to do the same /exact/ thing as my proposed
typedef
 block, you're looking at reproducing the behavior in roughly 12 methods
and
 members that are already available in char[char[]].  I know that using a
class
 is the best way ahead for now, but extending typedef this way leads to
much more
 maintainable code IMO.

 - Pragma
Aug 04 2004
prev sibling parent reply Sean Kelly <sean f4.ca> writes:
In article <ceq4g5$236p$1 digitaldaemon.com>, Ivan Senji says...
I don't know if this helps:


typedef char[][char[]] AttributeSet;

char[] getAttribute(AttributeSet a, char[] x)
{
    //do something
}

void main ()
{
     AttributeSet set;
     set["name"] = "foo";
     set["color"] = "red";
     set.getAttribute("BLA");
}
Holy cow! That works? Fantastic :) My evil mind is already reeling with the possibilities. I'll have to chalk that one up as yet another often requested C++ feature that D already has. Sean
Aug 04 2004
parent reply Sean Kelly <sean f4.ca> writes:
In article <cer02j$2pe$1 digitaldaemon.com>, Sean Kelly says...
In article <ceq4g5$236p$1 digitaldaemon.com>, Ivan Senji says...
I don't know if this helps:


typedef char[][char[]] AttributeSet;

char[] getAttribute(AttributeSet a, char[] x)
{
    //do something
}

void main ()
{
     AttributeSet set;
     set["name"] = "foo";
     set["color"] = "red";
     set.getAttribute("BLA");
}
Holy cow! That works? Fantastic :) My evil mind is already reeling with the possibilities. I'll have to chalk that one up as yet another often requested C++ feature that D already has.
Quick update: this only works for array types. If possible, I'd like to request to it work for all primitive types. Sean
Aug 04 2004
next sibling parent pragma <EricAnderton at yahoo dot com> <pragma_member pathlink.com> writes:
In article <cergqb$g58$1 digitaldaemon.com>, Sean Kelly says...
In article <cer02j$2pe$1 digitaldaemon.com>, Sean Kelly says...
In article <ceq4g5$236p$1 digitaldaemon.com>, Ivan Senji says...
I don't know if this helps:


typedef char[][char[]] AttributeSet;

char[] getAttribute(AttributeSet a, char[] x)
{
    //do something
}

void main ()
{
     AttributeSet set;
     set["name"] = "foo";
     set["color"] = "red";
     set.getAttribute("BLA");
}
Holy cow! That works? Fantastic :) My evil mind is already reeling with the possibilities. I'll have to chalk that one up as yet another often requested C++ feature that D already has.
Quick update: this only works for array types. If possible, I'd like to request to it work for all primitive types.
Walter, I'd like to second this, as I wouldn't mind seeing functions work like this for _all_ primitive types as well. To recap: test.d(15): no property 'abs' for type 'int' Also, the ability to override operators for primitives in a similar way would really expand the role of primitive types in D. test.d(7): function expected before (), not 'int[]' - Pragma
Aug 04 2004
prev sibling parent "Ivan Senji" <ivan.senji public.srce.hr> writes:
"Sean Kelly" <sean f4.ca> wrote in message
news:cergqb$g58$1 digitaldaemon.com...
 In article <cer02j$2pe$1 digitaldaemon.com>, Sean Kelly says...
In article <ceq4g5$236p$1 digitaldaemon.com>, Ivan Senji says...
I don't know if this helps:


typedef char[][char[]] AttributeSet;

char[] getAttribute(AttributeSet a, char[] x)
{
    //do something
}

void main ()
{
     AttributeSet set;
     set["name"] = "foo";
     set["color"] = "red";
     set.getAttribute("BLA");
}
Holy cow! That works? Fantastic :) My evil mind is already reeling
with the
possibilities.  I'll have to chalk that one up as yet another often
requested
C++ feature that D already has.
Quick update: this only works for array types. If possible, I'd like to
request
 to it work for all primitive types.
When i first learned about this feature i was also little dissapointed about it working only for arrays, and i had the same request, but over time i realized that although this could be useful for all primitive types, it is most useful for arrays.
 Sean
Aug 04 2004