Thread overview | |||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
August 04, 2004 Typedef blocks | ||||
---|---|---|---|---|
| ||||
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 Re: Typedef blocks | ||||
---|---|---|---|---|
| ||||
Posted in reply to pragma | 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 Re: Typedef blocks | ||||
---|---|---|---|---|
| ||||
Posted in reply to pragma | 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 Re: Typedef blocks | ||||
---|---|---|---|---|
| ||||
Posted in reply to Ivan Senji | 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 Re: Typedef blocks | ||||
---|---|---|---|---|
| ||||
Posted in reply to pragma | "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 Re: Typedef blocks | ||||
---|---|---|---|---|
| ||||
Posted in reply to Ivan Senji | 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 Re: Typedef blocks | ||||
---|---|---|---|---|
| ||||
Posted in reply to Ivan Senji | 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 Re: Typedef blocks | ||||
---|---|---|---|---|
| ||||
Posted in reply to Sean Kelly | 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 Feature Request (was Re: Typedef blocks) | ||||
---|---|---|---|---|
| ||||
Posted in reply to Sean Kelly | 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 Re: Typedef blocks | ||||
---|---|---|---|---|
| ||||
Posted in reply to Sean Kelly | "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 > > |
Copyright © 1999-2021 by the D Language Foundation