digitalmars.D - template+alias as an object's "namespace"
- F i L (51/51) Apr 17 2012 Would it be prudent to make Templates be able to be used without
- F i L (10/10) Apr 17 2012 Another possible syntax is, given the talked about:
- Gor Gyolchanyan (8/16) Apr 18 2012 I wanted this for a long time now. There were many situations when I
- F i L (5/10) Apr 18 2012 Yes I agree, there's been many times where I wanted this kind of
- Gor Gyolchanyan (12/20) Apr 18 2012 If you ask me, aesthetics is one of the most important parts of any
- kennytm (9/71) Apr 18 2012 struct Foo1 {
- F i L (14/22) Apr 18 2012 That fails when you add variables though:
- Timon Gehr (13/36) Apr 18 2012 struct Foo {
- F i L (24/43) Apr 19 2012 Foo.Unsafe.name is static and not per-instance. That's a
- Timon Gehr (41/84) Apr 19 2012 Ah, I see what you are getting at. I failed to read your post carefully
- F i L (73/93) Apr 19 2012 Yes, but my request is to have an un-parameter-atized syntax
- Sebastian Graf (32/33) May 14 2013 Sorry to dig this up again, but I'm looking for something to
Would it be prudent to make Templates be able to be used without parameters? (Or something along those lines) Consider the following: struct Foo1 { string name = "Foo1"; alias Unsafe!() unsafe; template Unsafe() { string name = "Bar"; void bar() { writeln(this.name, name); } } } struct Foo2 { string name = "Foo2"; string unsafe_name = "Bar"; void unsafe_bar() { writeln(name, unsafe_name); } } void main() { auto foo1 = Foo1(); auto foo2 = Foo2(); foo1.Unsafe!().bar(); // ugly foo1.unsafe.bar(); // nice foo2.unsafe_bar(); // classic } The classic way works, or course, but it's not as pretty :) I may be breaking some sacred rule of OOP here, but I think this kind of classification comes in handy. In fact, I think D's the only language that actually allows for this syntax without increasing an objects memory footprints. It could be *useful* in situations where you want to simplistically wrap a complex system, say X11, and provide _a few_ convenience functions, while still providing complete access to X11 objects, but grouping them into logical subsection. Example: class Window { private XDisplay* _display; void create(...) { /* use _display; */ } void delete(...) { /* ditto */ } template X11 { property auto display() { return _display; } } } The only thing that erks me is the name "template" doesn't really match it's function at this point. Maybe something like "alias template" would make more sense: alias template X11 { ... } idk. What are peoples thoughts on this? Good? Bad? Ugly?
Apr 17 2012
Another possible syntax is, given the talked about: alias name = type; syntax, we could just use that in combination with "anonymous templates": alias X11 = template { property auto display() { return _display; } } Though, now that I look at it I'm kinda just like parameterless templates: template X11 { ... }
Apr 17 2012
I wanted this for a long time now. There were many situations when I needed just that, but I didn't want to invent dummy structures for that, because I didn't want any run-time change. On Wed, Apr 18, 2012 at 3:04 AM, F i L <witte2008 gmail.com> wrote:Another possible syntax is, given the talked about: =C2=A0alias name =3D type; syntax, we could just use that in combination with "anonymous templates": =C2=A0alias X11 =3D template { =C2=A0 =C2=A0 property auto display() { return _display; } =C2=A0} Though, now that I look at it I'm kinda just like parameterless templates=:=C2=A0template X11 { ... }--=20 Bye, Gor Gyolchanyan.
Apr 18 2012
On Wednesday, 18 April 2012 at 10:04:07 UTC, Gor Gyolchanyan wrote:I wanted this for a long time now. There were many situations when I needed just that, but I didn't want to invent dummy structures for that, because I didn't want any run-time change.Yes I agree, there's been many times where I wanted this kind of compositional ability... but It looks like you and I are the only ones interested in these sorts of aesthetics.
Apr 18 2012
If you ask me, aesthetics is one of the most important parts of any programming language. Any programming language is an intermediate between human language and machine language. Quality code generation defines how good the language speaks in machine. Convenient syntax defines how good the language speaks human. In this respect, making the language prettier is just as important as making the code it generates faster. On Wed, Apr 18, 2012 at 8:12 PM, F i L <witte2008 gmail.com> wrote:On Wednesday, 18 April 2012 at 10:04:07 UTC, Gor Gyolchanyan wrote:-- Bye, Gor Gyolchanyan.I wanted this for a long time now. There were many situations when I needed just that, but I didn't want to invent dummy structures for that, because I didn't want any run-time change.Yes I agree, there's been many times where I wanted this kind of compositional ability... but It looks like you and I are the only ones interested in these sorts of aesthetics.
Apr 18 2012
"F i L" <witte2008 gmail.com> wrote:Would it be prudent to make Templates be able to be used without parameters? (Or something along those lines) Consider the following: struct Foo1 { string name = "Foo1"; alias Unsafe!() unsafe; template Unsafe() { string name = "Bar"; void bar() { writeln(this.name, name); } } } struct Foo2 { string name = "Foo2"; string unsafe_name = "Bar"; void unsafe_bar() { writeln(name, unsafe_name); } } void main() { auto foo1 = Foo1(); auto foo2 = Foo2(); foo1.Unsafe!().bar(); // ugly foo1.unsafe.bar(); // nice foo2.unsafe_bar(); // classic } The classic way works, or course, but it's not as pretty :) I may be breaking some sacred rule of OOP here, but I think this kind of classification comes in handy. In fact, I think D's the only language that actually allows for this syntax without increasing an objects memory footprints. It could be *useful* in situations where you want to simplistically wrap a complex system, say X11, and provide _a few_ convenience functions, while still providing complete access to X11 objects, but grouping them into logical subsection. Example: class Window { private XDisplay* _display; void create(...) { /* use _display; */ } void delete(...) { /* ditto */ } template X11 { property auto display() { return _display; } } } The only thing that erks me is the name "template" doesn't really match it's function at this point. Maybe something like "alias template" would make more sense: alias template X11 { ... } idk. What are peoples thoughts on this? Good? Bad? Ugly?struct Foo1 { struct Unsafe { static: void bar() { ... } } } Foo1 f; f.Unsafe.bar();
Apr 18 2012
kennytm wrote:struct Foo1 { struct Unsafe { static: void bar() { ... } } } Foo1 f; f.Unsafe.bar();That fails when you add variables though: struct Foo { struct Unsafe { string name; static void bar() { writeln(name); // error: needs 'this' } } } Like I said, it's completely possible with templates today, you just have to alias them for nice syntax. Parameterless templates would just be sugar, but that sugar would be nice when you want to use classifications like this in real code.
Apr 18 2012
On 04/19/2012 01:41 AM, F i L wrote:kennytm wrote:struct Foo { struct Unsafe { static: string name; void bar() { writeln(name); // fine } } }struct Foo1 { struct Unsafe { static: void bar() { ... } } } Foo1 f; f.Unsafe.bar();That fails when you add variables though: struct Foo { struct Unsafe { string name; static void bar() { writeln(name); // error: needs 'this' } } }Like I said, it's completely possible with templates today, you just have to alias them for nice syntax. Parameterless templatesIt is not really a 'template' if it is parameterless and does not need to be instantiated.would just be sugar, but that sugar would be nice when you want to use classifications like this in real code.This idiom imho shouldn't be overused. Renamed imports usually suffice.
Apr 18 2012
Timon Gehr wrote:struct Foo { struct Unsafe { static: string name; void bar() { writeln(name); // fine } } }Foo.Unsafe.name is static and not per-instance. That's a completely different thing than having a "namespace" within the object which serves only as a semantic layer to classify property access.Sure it is. Templates provide a semantic convenience over reusable bits of code that get resolved at CT. It's more like a CT struct than a CT function. So it makes perfect sense to have parameterless ones, especially because you can already have that, only with less pretty code.Like I said, it's completely possible with templates today, you just have to alias them for nice syntax. Parameterless templatesIt is not really a 'template' if it is parameterless and does not need to be instantiated.I don't see how import renaming applies to what I've suggested. It's a completely different topic. I'm sure it could be abused, like anything else, but It is useful in some areas, and I don't see any reason not to have a usable syntax for something that's already achievable in D. Honestly I think this could be another "nah nah nah, look what our language can do" bullet point in D's favor. So far as I know, no other (efficient) language can sub-classify it's objects without increasing their per-instance memory footprint + require manually wiring up the connection. While in D it's simply an emergent feature of a beautiful template design. D gives more control over the structure of objects than any other language, without sacrificing a thing. That sounds like a good marketing point to me :)would just be sugar, but that sugar would be nice when you want to use classifications like this in real code.This idiom imho shouldn't be overused. Renamed imports usually suffice.
Apr 19 2012
On 04/19/2012 09:45 PM, F i L wrote:Timon Gehr wrote:Ah, I see what you are getting at. I failed to read your post carefully enough. Sorry about that.struct Foo { struct Unsafe { static: string name; void bar() { writeln(name); // fine } } }Foo.Unsafe.name is static and not per-instance. That's a completely different thing than having a "namespace" within the object which serves only as a semantic layer to classify property access.It is a parameterized scope that is analysed upon instantiation.Sure it is. Templates provide a semantic convenience over reusable bits of code that get resolved at CT. It's more like a CT struct than a CT function.Like I said, it's completely possible with templates today, you just have to alias them for nice syntax. Parameterless templatesIt is not really a 'template' if it is parameterless and does not need to be instantiated.So it makes perfect sense to have parameterless ones, especially because you can already have that, only with less pretty code.This is an alternative: private template _unsafe(){ string name; void bar() { writeln(name); } } struct Foo{ mixin _unsafe Unsafe; } Is this better? (_unsafe can be a local template of struct Foo, but then it invades the allMembers) In fact, this pattern could be generalized to template Classify(string s){mixin(s);} struct Foo{ mixin Classify!q{ string name; void bar() { writeln(name); } } Unsafe; } With the alternate alias syntax, this would then probably work as well: template Classify(string s){mixin(s);} struct Foo{ mixin Unsafe = Classify!q{ string name; void bar() { writeln(name); } } }It is similar, but here it does indeed not apply.I don't see how import renaming applies to what I've suggested. It's a completely different topic.would just be sugar, but that sugar would be nice when you want to use classifications like this in real code.This idiom imho shouldn't be overused. Renamed imports usually suffice.I'm sure it could be abused, like anything else, but It is useful in some areas, and I don't see any reason not to have a usable syntax for something that's already achievable in D.I think the current syntax hardly qualifies as unusable. I agree that it is not the prettiest/most specific one imaginable.Honestly I think this could be another "nah nah nah, look what our language can do" bullet point in D's favor. So far as I know, no other (efficient) language can sub-classify it's objects without increasing their per-instance memory footprint + require manually wiring up the connection. While in D it's simply an emergent feature of a beautiful template design.Well, it can do it already.D gives more control over the structure of objects than any other language, without sacrificing a thing. That sounds like a good marketing point to me :)D's design sacrifices ease of implementation to some extent.
Apr 19 2012
Timon Gehr wrote:Ah, I see what you are getting at. I failed to read your post carefully enough. Sorry about that.Hakuna matata ;)It is a parameterized scope that is analysed upon instantiation.Yes, but my request is to have an un-parameter-atized syntax which is sugar for a template with zero parameters and is useful for sub-scoping objects. See below for a more detailed argument.This is an alternative: private template _unsafe(){ string name; void bar() { writeln(name); } } struct Foo{ mixin _unsafe Unsafe; } Is this better? (_unsafe can be a local template of struct Foo, but then it invades the allMembers)Not really. Reasons is I actually want _unsafe to be part of allMembers, but I also want to use it in a syntactically appealing way. Also, by separating the template from the object, you're (conceptually) breaking OOP design, unless _unsafe is designed as a reusable packet of code (ie, used by more than just Foo, like UFCS), which isn't the goal I intended. Here's another example: class Fighter : Ship { template visual { VisualMesh mesh; void update() { /* use visual.mesh */ } void updateAfter() { /* ditto */ } } template physic { CollisionMesh mesh; void udpate() { /* use physic.mesh */ } } void update() { visual.mesh.doSomething(); physic.mesh.doSomething(); } } Now we have three functions "update", and two fields "mesh", without any conflicts because they're separated by scope. The classic way to do this is simply to prefix the names: visualMesh, visualUpdate, physicMesh, etc... but scoping fits with OOP design, and allows each sub-scope to use each variable without prefixing, eg, "visual.update()" doesn't need to prefix "visual." when using "visual.mesh". I know that this can be today, though alternative ways. However, this requires very little prior knowledge of D's idioms to understand. Meaning non-D programmers will understand this at a glance. It makes sense, and code is where it should be, saving us all a little bit of head-ache. What may also be prudent, is to have parameterless mixin templates, something like: struct Person { mixin intros = template { void sayHi() { ... } void sayAge() { ... } } void sayHi() { intros.sayHi(); intros.sayAge(); } } void main() { auto philip = Person(); philip.sayHi(); philip.sayAge(); philip.intros.sayHi(); } The problem with always using mixin templates is that sometime you want to require the scope prefix, like in the Ship example above.I think the current syntax hardly qualifies as unusable. I agree that it is not the prettiest/most specific one imaginable.Agreed, though I don't see that as a reason to not *eventually* introduce a more usable syntax. If I had more time to dick around with DMD's internals, I'd make a pull request myself. I'm learning it, but it'll be awhile before I'll be trying to push code.Well, it can do it already.Yes it can, but just even simple realiasing a template (or separating it out like your examples) requires a deeper understanding of D than what's graspable from my simple Ship example above. The easier to grasp, the more passing developer it will impress.D's design sacrifices ease of implementation to some extent.I don't think it needs too, though. We could have both.
Apr 19 2012
On Thursday, 19 April 2012 at 22:24:52 UTC, F i L wrote:snipSorry to dig this up again, but I'm looking for something to provide stubs for a compile time interface in a struct: mixin template Stubs() { template __Stubs__() { void sayHi() { writeln("hi"); } } alias __Stubs__!() this; } struct Foo { mixin Stubs; } void main() { Foo().sayHi(); } This is so that I am still able to override sayHi() at compile time with my own implementation in Foo. I would love to do that, but it won't compile right now. If I alias to something else than this, it works though. I could alias-this with an inner struct, i.e. when I change the template mixin to mixin template Stubs() { struct __Stubs__ { void sayHi() { writeln("hi"); } } private __Stubs__ __s; alias __s this; } But this means I have to sacrifice some bytes in Foo to store the super struct, noticable as you add fields to Foo. This is not too bad, but since we have templates and mixins and stuff, is there maybe a way I haven't thought about?
May 14 2013