www.digitalmars.com         C & C++   DMDScript  

digitalmars.D - template+alias as an object's "namespace"

reply "F i L" <witte2008 gmail.com> writes:
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
next sibling parent "F i L" <witte2008 gmail.com> writes:
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
prev sibling next sibling parent Gor Gyolchanyan <gor.f.gyolchanyan gmail.com> writes:
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
prev sibling next sibling parent "F i L" <witte2008 gmail.com> writes:
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
prev sibling next sibling parent Gor Gyolchanyan <gor.f.gyolchanyan gmail.com> writes:
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:
 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.

-- Bye, Gor Gyolchanyan.
Apr 18 2012
prev sibling next sibling parent reply kennytm <kennytm gmail.com> writes:
"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
parent reply Timon Gehr <timon.gehr gmx.ch> writes:
On 04/19/2012 01:41 AM, F i L wrote:
 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' } } }

struct Foo { struct Unsafe { static: string name; void bar() { writeln(name); // fine } } }
 Like I said, it's completely possible with templates today, you just
 have to alias them for nice syntax. Parameterless templates

It 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
parent Timon Gehr <timon.gehr gmx.ch> writes:
On 04/19/2012 09:45 PM, F i L wrote:
 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.

Ah, I see what you are getting at. I failed to read your post carefully enough. Sorry about that.
 Like I said, it's completely possible with templates today, you just
 have to alias them for nice syntax. Parameterless templates

It is not really a 'template' if it is parameterless and does not need to be instantiated.

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.

It is a parameterized scope that is analysed upon instantiation.
 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); } } }
 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 don't see how import renaming applies to what I've suggested. It's a completely different topic.

It is similar, but here it does indeed not apply.
 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
prev sibling next sibling parent "F i L" <witte2008 gmail.com> writes:
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
prev sibling next sibling parent "F i L" <witte2008 gmail.com> writes:
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.
 Like I said, it's completely possible with templates today, 
 you just
 have to alias them for nice syntax. Parameterless templates

It is not really a 'template' if it is parameterless and does not need to be instantiated.

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.
 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 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 :)
Apr 19 2012
prev sibling next sibling parent "F i L" <witte2008 gmail.com> writes:
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
prev sibling parent "Sebastian Graf" <SebastianGraf t-online.de> writes:
On Thursday, 19 April 2012 at 22:24:52 UTC, F i L wrote:
 snip

Sorry 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