Jump to page: 1 2
Thread overview
Typedef blocks
Aug 04, 2004
pragma
Aug 04, 2004
Regan Heath
Aug 04, 2004
Ivan Senji
Aug 04, 2004
pragma
Aug 04, 2004
Ivan Senji
Aug 04, 2004
pragma
Aug 04, 2004
Ivan Senji
Aug 04, 2004
Sean Kelly
Aug 04, 2004
Sean Kelly
Feature Request (was Re: Typedef blocks)
Aug 04, 2004
pragma
Aug 04, 2004
Ivan Senji
August 04, 2004
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:

# typedef char[][char[]] AttributeSet;

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

# char[] getAttribute(AttributeSet attribs,char[] name);
# char[] getRequiredAttribute(AttributeSet attribs,char[] name);

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

# AttributeSet set;
# set["name"] = "foo";
# set["color"] = "red";

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.

# typedef char[][char[]] AttributeSet{
#     char[] getAttribute(char[] name){
#         return(this[name]);
#     }
#     char[] getRequiredAttribute(char[] name){
#         char[] value = this[name];
#         if(!value) throw new Error(name ~ " is required.");
#         return(value);
#     }
# }

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

# AttributeSet set;
# set["name"] = "foo";
# set["color"] = "red";
#
# // elsewhere...
# char[] foo = set.getAttribute("foo");
# char[] bar = set.getRequiredAttribute("red");


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


August 04, 2004
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:
>
> # typedef char[][char[]] AttributeSet;
>
> In order to organize access to this type I have to write several functions to
> better encapsulate all the repeated bits that I use.
>
> # char[] getAttribute(AttributeSet attribs,char[] name);
> # char[] getRequiredAttribute(AttributeSet attribs,char[] name);
>
> The attribs would be set using the type's built-in array indexing.
>
> # AttributeSet set;
> # set["name"] = "foo";
> # set["color"] = "red";
>
> 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.
>
> # typedef char[][char[]] AttributeSet{
> #     char[] getAttribute(char[] name){
> #         return(this[name]);
> #     }
> #     char[] getRequiredAttribute(char[] name){
> #         char[] value = this[name];
> #         if(!value) throw new Error(name ~ " is required.");
> #         return(value);
> #     }
> # }
>
> This would allow AttributeSet, for example, to behave as a "char[][char[]]"
> while having methods that are passed the instance implicitly via "this".
>
> # AttributeSet set;
> # set["name"] = "foo";
> # set["color"] = "red";
> #
> # // elsewhere...
> # char[] foo = set.getAttribute("foo");
> # char[] bar = set.getRequiredAttribute("red");
>
>
> 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/
August 04, 2004
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:
>
> # typedef char[][char[]] AttributeSet;
>
> In order to organize access to this type I have to write several functions
to
> better encapsulate all the repeated bits that I use.
>
> # char[] getAttribute(AttributeSet attribs,char[] name);
> # char[] getRequiredAttribute(AttributeSet attribs,char[] name);
>
> The attribs would be set using the type's built-in array indexing.
>
> # AttributeSet set;
> # set["name"] = "foo";
> # set["color"] = "red";
>
> 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.
>
> # typedef char[][char[]] AttributeSet{
> #     char[] getAttribute(char[] name){
> #         return(this[name]);
> #     }
> #     char[] getRequiredAttribute(char[] name){
> #         char[] value = this[name];
> #         if(!value) throw new Error(name ~ " is required.");
> #         return(value);
> #     }
> # }
>
> This would allow AttributeSet, for example, to behave as a
"char[][char[]]"
> while having methods that are passed the instance implicitly via "this".
>
> # AttributeSet set;
> # set["name"] = "foo";
> # set["color"] = "red";
> #
> # // elsewhere...
> # char[] foo = set.getAttribute("foo");
> # char[] bar = set.getRequiredAttribute("red");
>
>
> 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
>
>


August 04, 2004
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).

# alias WindowEventDelegate void delegate(char[]);
# typedef WindowEventDelegate[] WindowEvent;
#
# void opCall(char[] reason){
#     foreach(WindowEventDelegate d; this){
#         d(reason);
#     }
# }

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


August 04, 2004
"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).
>
> # alias WindowEventDelegate void delegate(char[]);
> # typedef WindowEventDelegate[] WindowEvent;
> #
> # void opCall(char[] reason){
> #     foreach(WindowEventDelegate d; this){
> #         d(reason);
> #     }
> # }
>
> 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
>
>


August 04, 2004
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


August 04, 2004
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.

>> # alias WindowEventDelegate void delegate(char[]);
>> # typedef WindowEventDelegate[] WindowEvent;
>> #
>> # void opCall(char[] reason){
>> #     foreach(WindowEventDelegate d; this){
>> #         d(reason);
>> #     }
>> # }
>>
>> 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


August 04, 2004
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


August 04, 2004
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:
# int sum(int[] list){
#     int result = 0;
#     foreach(int i; list) result += i;
#     return result;
# }
#
# int abs(int value){
#     return value < 0 ? -value : value;
# }
#
# void main(){
#    int[] list;
#    int value;
#    value = list.sum(); // works great! (thank you Walter)
#    value.abs(); // compiler complains (see below) :(
# }

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.

# void opCall(int[] value){
# }
#
# void main(){
#     int value[];
#     value.opCall(); // works, but not what was intended
#     value(); // compiler complains (below)
# }

test.d(7): function expected before (), not 'int[]'

- Pragma


August 04, 2004
"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
>
>


« First   ‹ Prev
1 2