www.digitalmars.com         C & C++   DMDScript  

digitalmars.D - internal/local template memebers

reply BCS <ao pathlink.com> writes:
A number of times while working with template code I have found that I need 
a variable inside a template but don't want the side effects of doing so. 
Specifically 1) having a tmp variable results in having to explicitly reference 
template members rather than being able to use the default member rule and 
2) the extra symbols seem to result in a substantial increases in the compile 
time memory usage.

The idea I'm floating would be to have a "local" storage class (or whatever 
keyword is chosen) that would only be accessible from within the template 
it is declared in:


template Foo(char[] str)
{
    local char[] first = str[0..$/2];
    local char[] last = str[$/2..$];

    const char[] Foo = Foo!(first) ~ Foo!(last); // legal; note not "Foo!().Foo"
    // const char[] Foo = Foo!(first).a ~ Foo!(last).a; // error a is not 
accessible
}

During compilation these variables would be computed, used and thrown away 
resulting in no long term memory cost.
Oct 24 2008
next sibling parent reply "Bill Baxter" <wbaxter gmail.com> writes:
On Sat, Oct 25, 2008 at 1:05 PM, BCS <ao pathlink.com> wrote:
 A number of times while working with template code I have found that I need
 a variable inside a template but don't want the side effects of doing so.
 Specifically 1) having a tmp variable results in having to explicitly
 reference template members rather than being able to use the default member
 rule and 2) the extra symbols seem to result in a substantial increases in
 the compile time memory usage.

 The idea I'm floating would be to have a "local" storage class (or whatever
 keyword is chosen) that would only be accessible from within the template it
 is declared in:


 template Foo(char[] str)
 {
   local char[] first = str[0..$/2];
   local char[] last = str[$/2..$];

   const char[] Foo = Foo!(first) ~ Foo!(last); // legal; note not
 "Foo!().Foo"
   // const char[] Foo = Foo!(first).a ~ Foo!(last).a; // error a is not
 accessible
 }

 During compilation these variables would be computed, used and thrown away
 resulting in no long term memory cost.
Indeed. You're resurrecting a classic. Maybe a good time to do so, though. Lots of uses for this suggestion -- internal helper functions, local aliases for unwieldy types. I've wished for it many times, too. Another way to go would just be to say if you have a symbol with the same name as the template inside, then it automatically means everything else is hidden. --- Another gripe is having to repeat the exact template name over and over in code like this. This template ThisIsTheTemplateNameFoo(char[] str) { const char[] ThisIsTheTemplateName = ThisIsTheTemplateName!(str[0..$/2]) ~ ThisIsTheTemplateName!(str[$/2..$]); } I think "this" for constructors has taught us that not repeating the name of something when the compiler already knows it is a "honking great idea". It should be extended to templates somehow too. --bb
Oct 24 2008
parent BCS <ao pathlink.com> writes:
Reply to Bill,

 Indeed.  You're resurrecting a classic.  Maybe a good time to do so,
 though.  Lots of uses for this suggestion -- internal helper
 functions, local aliases for unwieldy types.  I've wished for it many
 times, too.
 
 Another way to go would just be to say if you have a symbol with the
 same name as the template inside, then it automatically means
 everything else is hidden.
truth be told, that use is not the main reason I want this. The reduced memory usage is (when you have compiles that use up >1GB you start to think of these things).
Oct 24 2008
prev sibling parent reply "Denis Koroskin" <2korden gmail.com> writes:
On Sat, 25 Oct 2008 08:05:41 +0400, BCS <ao pathlink.com> wrote:

 A number of times while working with template code I have found that I  
 need a variable inside a template but don't want the side effects of  
 doing so. Specifically 1) having a tmp variable results in having to  
 explicitly reference template members rather than being able to use the  
 default member rule and 2) the extra symbols seem to result in a  
 substantial increases in the compile time memory usage.

 The idea I'm floating would be to have a "local" storage class (or  
 whatever keyword is chosen) that would only be accessible from within  
 the template it is declared in:


 template Foo(char[] str)
 {
     local char[] first = str[0..$/2];
     local char[] last = str[$/2..$];

     const char[] Foo = Foo!(first) ~ Foo!(last); // legal; note not  
 "Foo!().Foo"
     // const char[] Foo = Foo!(first).a ~ Foo!(last).a; // error a is  
 not accessible
 }

 During compilation these variables would be computed, used and thrown  
 away resulting in no long term memory cost.
I agree! But I would prefer re-using public/private - they make perfect sense here - instead of new internal/local keywords.
Oct 25 2008
next sibling parent reply "Bill Baxter" <wbaxter gmail.com> writes:
On Sat, Oct 25, 2008 at 8:48 PM, Denis Koroskin <2korden gmail.com> wrote:
 On Sat, 25 Oct 2008 08:05:41 +0400, BCS <ao pathlink.com> wrote:

 A number of times while working with template code I have found that I
 need a variable inside a template but don't want the side effects of doing
 so. Specifically 1) having a tmp variable results in having to explicitly
 reference template members rather than being able to use the default member
 rule and 2) the extra symbols seem to result in a substantial increases in
 the compile time memory usage.

 The idea I'm floating would be to have a "local" storage class (or
 whatever keyword is chosen) that would only be accessible from within the
 template it is declared in:


 template Foo(char[] str)
 {
    local char[] first = str[0..$/2];
    local char[] last = str[$/2..$];

    const char[] Foo = Foo!(first) ~ Foo!(last); // legal; note not
 "Foo!().Foo"
    // const char[] Foo = Foo!(first).a ~ Foo!(last).a; // error a is not
 accessible
 }

 During compilation these variables would be computed, used and thrown away
 resulting in no long term memory cost.
I agree! But I would prefer re-using public/private - they make perfect sense here - instead of new internal/local keywords.
Problem is templates can be mixed in. And in that case public/private has meaning in the context of the host. --bb
Oct 25 2008
parent reply "Denis Koroskin" <2korden gmail.com> writes:
On Sat, 25 Oct 2008 17:08:28 +0400, Bill Baxter <wbaxter gmail.com> wrote:

 On Sat, Oct 25, 2008 at 8:48 PM, Denis Koroskin <2korden gmail.com>  
 wrote:
 On Sat, 25 Oct 2008 08:05:41 +0400, BCS <ao pathlink.com> wrote:

 A number of times while working with template code I have found that I
 need a variable inside a template but don't want the side effects of  
 doing
 so. Specifically 1) having a tmp variable results in having to  
 explicitly
 reference template members rather than being able to use the default  
 member
 rule and 2) the extra symbols seem to result in a substantial  
 increases in
 the compile time memory usage.

 The idea I'm floating would be to have a "local" storage class (or
 whatever keyword is chosen) that would only be accessible from within  
 the
 template it is declared in:


 template Foo(char[] str)
 {
    local char[] first = str[0..$/2];
    local char[] last = str[$/2..$];

    const char[] Foo = Foo!(first) ~ Foo!(last); // legal; note not
 "Foo!().Foo"
    // const char[] Foo = Foo!(first).a ~ Foo!(last).a; // error a is  
 not
 accessible
 }

 During compilation these variables would be computed, used and thrown  
 away
 resulting in no long term memory cost.
I agree! But I would prefer re-using public/private - they make perfect sense here - instead of new internal/local keywords.
Problem is templates can be mixed in. And in that case public/private has meaning in the context of the host. --bb
I don't see how this is a problem: template Bar { private int value; public int getValue() { return value; } } class Foo { mixin Bar!(); } template Square(alias x) { private enum temp = x * x; public enum Square = temp; } enum x2 = Square!(x); This is because you usual templates and mixin templates are completely different, mixin'ing usual template or instantiating template that is intended for being mixed-in makes no sense in the majority of real cases. Moreover, I would prefer to separate these terms and so their syntax: mixin template Bar { private int value; public int getValue() { return value; } } class Foo { mixin Bar!(); } int bar = Bar!().getValue(); // Error: can't instantiate mixin template template Square(alias x) { private enum temp = x * x; public enum Square = temp; } class Test { mixin Square!(42); // Error: can't mixin non-mixin template }
Oct 25 2008
next sibling parent "Bill Baxter" <wbaxter gmail.com> writes:
On Sat, Oct 25, 2008 at 10:34 PM, Denis Koroskin <2korden gmail.com> wrote:
 On Sat, 25 Oct 2008 17:08:28 +0400, Bill Baxter <wbaxter gmail.com> wrote:

 On Sat, Oct 25, 2008 at 8:48 PM, Denis Koroskin <2korden gmail.com> wrote:
 On Sat, 25 Oct 2008 08:05:41 +0400, BCS <ao pathlink.com> wrote:
This is because you usual templates and mixin templates are completely different, mixin'ing usual template or instantiating template that is intended for being mixed-in makes no sense in the majority of real cases.
Good point. I can't think of any case where something I've written as a mixin would be useful as a stand-alone template. I usually end up calling my mixin templates something with "Mix" in the name. But it does seem like it would be tricky for the compiler to determine which case you meant. Unless you told it which case... which is exactly what you suggest next.
 Moreover, I would prefer to separate these terms and so their syntax:

 mixin template Bar
That sounds quite reasonable to me. (Though it's 4am and I just woke up, so I may not be at my peak right now) I would also appreciate templates being distict from mixin templates too. If you actually did run into some need for a template that can be either, then just mixin the mixin into a template! mixin template BarMix(T) { ... } template Bar(T) { mixin BarMix!(T); } --bb
Oct 25 2008
prev sibling parent "Bill Baxter" <wbaxter gmail.com> writes:
On Sun, Oct 26, 2008 at 3:54 AM, Bill Baxter <wbaxter gmail.com> wrote:
 On Sat, Oct 25, 2008 at 10:34 PM, Denis Koroskin <2korden gmail.com> wrote:
 On Sat, 25 Oct 2008 17:08:28 +0400, Bill Baxter <wbaxter gmail.com> wrote:

 On Sat, Oct 25, 2008 at 8:48 PM, Denis Koroskin <2korden gmail.com> wrote:
 On Sat, 25 Oct 2008 08:05:41 +0400, BCS <ao pathlink.com> wrote:
This is because you usual templates and mixin templates are completely different, mixin'ing usual template or instantiating template that is intended for being mixed-in makes no sense in the majority of real cases.
Good point. I can't think of any case where something I've written as a mixin would be useful as a stand-alone template. I usually end up calling my mixin templates something with "Mix" in the name. But it does seem like it would be tricky for the compiler to determine which case you meant. Unless you told it which case... which is exactly what you suggest next.
 Moreover, I would prefer to separate these terms and so their syntax:

 mixin template Bar
That sounds quite reasonable to me. (Though it's 4am and I just woke up, so I may not be at my peak right now)
Actually, I realized I do actually have some code that I use as either mixin or standalone. It's a template full of utility functions. Sometimes it's convenient just to mix all those utility functions into a class directly rather than having to go through the GeomUtil!(PointType) template. But it's a convenient set of functions that doesn't particularly need to be mixed in to be useful. --bb
Oct 25 2008
prev sibling parent reply "Bill Baxter" <wbaxter gmail.com> writes:
On Sat, Oct 25, 2008 at 10:08 PM, Bill Baxter <wbaxter gmail.com> wrote:
 On Sat, Oct 25, 2008 at 8:48 PM, Denis Koroskin <2korden gmail.com> wrote:
 On Sat, 25 Oct 2008 08:05:41 +0400, BCS <ao pathlink.com> wrote:

 A number of times while working with template code I have found that I
 need a variable inside a template but don't want the side effects of doing
 so. Specifically 1) having a tmp variable results in having to explicitly
 reference template members rather than being able to use the default member
 rule and 2) the extra symbols seem to result in a substantial increases in
 the compile time memory usage.

 The idea I'm floating would be to have a "local" storage class (or
 whatever keyword is chosen) that would only be accessible from within the
 template it is declared in:


 template Foo(char[] str)
 {
    local char[] first = str[0..$/2];
    local char[] last = str[$/2..$];

    const char[] Foo = Foo!(first) ~ Foo!(last); // legal; note not
 "Foo!().Foo"
    // const char[] Foo = Foo!(first).a ~ Foo!(last).a; // error a is not
 accessible
 }

 During compilation these variables would be computed, used and thrown away
 resulting in no long term memory cost.
I agree! But I would prefer re-using public/private - they make perfect sense here - instead of new internal/local keywords.
Problem is templates can be mixed in. And in that case public/private has meaning in the context of the host.
...But contextual keywords to the rescue! private(local) char[] first = str[0..$/2]; private(local) char[] last = str[$/2..$]; --bb
Oct 25 2008
parent KennyTM~ <kennytm gmail.com> writes:
Bill Baxter wrote:
 On Sat, Oct 25, 2008 at 10:08 PM, Bill Baxter <wbaxter gmail.com> wrote:
 On Sat, Oct 25, 2008 at 8:48 PM, Denis Koroskin <2korden gmail.com> wrote:
 On Sat, 25 Oct 2008 08:05:41 +0400, BCS <ao pathlink.com> wrote:

 A number of times while working with template code I have found that I
 need a variable inside a template but don't want the side effects of doing
 so. Specifically 1) having a tmp variable results in having to explicitly
 reference template members rather than being able to use the default member
 rule and 2) the extra symbols seem to result in a substantial increases in
 the compile time memory usage.

 The idea I'm floating would be to have a "local" storage class (or
 whatever keyword is chosen) that would only be accessible from within the
 template it is declared in:


 template Foo(char[] str)
 {
    local char[] first = str[0..$/2];
    local char[] last = str[$/2..$];

    const char[] Foo = Foo!(first) ~ Foo!(last); // legal; note not
 "Foo!().Foo"
    // const char[] Foo = Foo!(first).a ~ Foo!(last).a; // error a is not
 accessible
 }

 During compilation these variables would be computed, used and thrown away
 resulting in no long term memory cost.
I agree! But I would prefer re-using public/private - they make perfect sense here - instead of new internal/local keywords.
Problem is templates can be mixed in. And in that case public/private has meaning in the context of the host.
...But contextual keywords to the rescue! private(local) char[] first = str[0..$/2]; private(local) char[] last = str[$/2..$]; --bb
Sweet, suddenly contextual keywords become a viable solution to everything; first the new member functions, now this :). Why no one had suggested it before? (Although private(local) sounds like unnecessary redundancy here.)
Oct 25 2008