www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - CTFE & template predicates

reply =?iso-8859-1?Q?Robert_M._M=FCnch?= <robert.muench saphirion.com> writes:
Hi, I have now played a around couple of hours (reading everything I 
could find) to get something to work, but I think I'm missing some 
basic concepts/understanding. Maybe someone can enlighten me how these 
things work. I thought that some code from David Nadlinger is what I'm 
searching for but don't know how to exactly make use of it.

Here is the code: I want to filter out some of the "allMembers" and use 
them in my code for a switch/final to check that call cases that were 
not filtered are covered. Trying to build the enum for the switch/final 
statement.

auto org_rules = TypeTuple!(__traits(allMembers,BolSource));
static assert(!isTypeTuple!(org_rules));

template startsNotWith(T,char C){
    static if (T[0] != C){
        enum startsNotWith = true;
    } else {
        enum startsNotWith = false;
    }
}

template StaticFilter(alias pred, T...) {
  static if (T.length == 0) {
    alias TypeTuple!() StaticFilter;
  } else static if (pred!(T[0])) {
    alias TypeTuple!(T[0], StaticFilter!(pred, T[1 .. $])) StaticFilter;
  } else {
    alias StaticFilter!(pred, T[1 .. $]) StaticFilter;
  }
}

alias startsNotWithp = startsNotWith!(T,"p"); // doesn't compile: 
Error: undefined identifier T

alias rules = StaticFilter!(startsNotWithp, org_rules);


While playing with this a couple of questions came up:

1. How do predicates get their argument(s)? I saw code where only the 
predicate was mentioned but no arguments. So, I assume there is some 
behind-the-curtain-magic going on. I read about things like "a == b" 
where I can reference 'a and 'b in a string.

2. "enum startsNotwith = false" So this is the return syntax for a CTFE 
for "return(true)" ?

3. TupleType is a very missleading name when you are learning these 
things, because the tuple can hold values as well. Or is there a more 
extensive explanation for the name I don't get?

4. Are there any tutorials about CTFE? This seems to be a very powerful 
but not so easy to use feature of D, but documentation is quite limited.

Thanks a lot.

-- 
Robert M. Münch
http://www.saphirion.com
smarter | better | faster
May 03 2015
next sibling parent reply "anonymous" <anonymous example.com> writes:
On Sunday, 3 May 2015 at 21:46:11 UTC, Robert M. Münch wrote:
 Hi, I have now played a around couple of hours (reading 
 everything I could find) to get something to work, but I think 
 I'm missing some basic concepts/understanding. Maybe someone 
 can enlighten me how these things work. I thought that some 
 code from David Nadlinger is what I'm searching for but don't 
 know how to exactly make use of it.

 Here is the code: I want to filter out some of the "allMembers" 
 and use them in my code for a switch/final to check that call 
 cases that were not filtered are covered. Trying to build the 
 enum for the switch/final statement.

 auto org_rules = TypeTuple!(__traits(allMembers,BolSource));
 static assert(!isTypeTuple!(org_rules));

 template startsNotWith(T,char C){
    static if (T[0] != C){
        enum startsNotWith = true;
    } else {
        enum startsNotWith = false;
    }
 }
Here T would have to be a type. But you want to accept a string. So: ---- template startsNotWith(string s,char c){ enum startsNotWith = s.length == 0 || s[0] != c; } ----
 template StaticFilter(alias pred, T...) {
  static if (T.length == 0) {
    alias TypeTuple!() StaticFilter;
  } else static if (pred!(T[0])) {
    alias TypeTuple!(T[0], StaticFilter!(pred, T[1 .. $])) 
 StaticFilter;
  } else {
    alias StaticFilter!(pred, T[1 .. $]) StaticFilter;
  }
 }

 alias startsNotWithp = startsNotWith!(T,"p"); // doesn't 
 compile: Error: undefined identifier T
You need to turn T into a parameter, so that StaticFilter can set it. (And it's really a string again, so I'm renaming to s.) ---- template startsNotWithp(string s) { enum startsNotWithp = startsNotWith!(s, 'p'); } /* Shorthand syntax: enum startsNotWithp(string s) = startsNotWith!(s, 'p'); */ ----
 alias rules = StaticFilter!(startsNotWithp, org_rules);


 While playing with this a couple of questions came up:

 1. How do predicates get their argument(s)? I saw code where 
 only the predicate was mentioned but no arguments. So, I assume 
 there is some behind-the-curtain-magic going on. I read about 
 things like "a == b" where I can reference 'a and 'b in a 
 string.
Predicates are called/instantiated by the thing to which you pass them. StaticFilter instantiates pred for each element of the T tuple it's given. If some documentation doesn't say how the predicate will be called/instantiated, then it's probably assumed to be obvious. String predicates are turned into functions behind the curtains. The thing you instantiate with "a == b" turns it into `(a, b) {return a == b;}` and uses that. I think we don't do string predicates for templates like StaticFilter, though.
 2. "enum startsNotwith = false" So this is the return syntax 
 for a CTFE for "return(true)" ?
It's the template syntax for "return false". CTFE does normal functions at compile time, so there it's just "return false". ---- /* Template: */ template t() {enum t = false;} enum x = t!(); /* CTFE: */ bool f() {return false;} enum y = f(); ----
 3. TupleType is a very missleading name when you are learning 
 these things, because the tuple can hold values as well.
Yup. And std.traits.isTypeTuple only adds to the confusion.
 Or is there a more extensive explanation for the name I don't 
 get?
Not that I'm aware of.
 4. Are there any tutorials about CTFE? This seems to be a very 
 powerful but not so easy to use feature of D, but documentation 
 is quite limited.
CTFE is rather simple. It just allows you to use certain functions in a static (i.e. compile time) context. Templates are more tricky. If you mean templates, maybe having the right name helps.
May 03 2015
next sibling parent reply =?iso-8859-1?Q?Robert_M._M=FCnch?= <robert.muench saphirion.com> writes:
On 2015-05-03 23:28:00 +0000, anonymous said:

 Here T would have to be a type. But you want to accept a string. So:
 ----
 template startsNotWith(string s,char c){
      enum startsNotWith = s.length == 0 || s[0] != c;
 }
 ----
Hi, ok, just to better understand this (I have a C++ background (even quite old)): When I want to use some functions I need to specify the type? It's not possible to use T.length() which would compile if T is a string? I thought that it's just generic and I can throw in T.
 1. How do predicates get their argument(s)? I saw code where only the 
 predicate was mentioned but no arguments. So, I assume there is some 
 behind-the-curtain-magic going on. I read about things like "a == b" 
 where I can reference 'a and 'b in a string.
Predicates are called/instantiated by the thing to which you pass them. StaticFilter instantiates pred for each element of the T tuple it's given. If some documentation doesn't say how the predicate will be called/instantiated, then it's probably assumed to be obvious.
Well, and often it's obvious that it's not obvious ;-)
 String predicates are turned into functions behind the curtains. The 
 thing you instantiate with "a == b" turns it into `(a, b) {return a == 
 b;}` and uses that. I think we don't do string predicates for templates 
 like StaticFilter, though.
Ok, that helps to better understand how this works. Thanks for the feedback. -- Robert M. Münch http://www.saphirion.com smarter | better | faster
May 04 2015
parent "anonymous" <anonymous example.com> writes:
On Monday, 4 May 2015 at 11:22:16 UTC, Robert M. Münch wrote:
 Hi, ok, just to better understand this (I have a C++ background 
 (even quite old)): When I want to use some functions I need to 
 specify the type? It's not possible to use T.length() which 
 would compile if T is a string? I thought that it's just 
 generic and I can throw in T.
In template parameter lists, a solitary identifier is a type parameter. You can only pass types in those. In function (pointer) declarations, a solitary identifier is the type of the parameter. In function/delegate literals, a solitary identifier is the name of the parameter and the type is inferred. I guess this is what you were thinking of. ---- void main() { template t(T) {} /* T is a template type parameter. */ alias i = t!int; /* It can be instantiated with the type int, for example, */ static assert(!__traits(compiles, t!123)); /* but not with a value. */ void function(int) fp; /* int is the type of the parameter. */ fp = (x) {}; /* x is the name of the parameter whose type is inferred from above. */ } ----
May 04 2015
prev sibling next sibling parent reply =?iso-8859-1?Q?Robert_M._M=FCnch?= <robert.muench saphirion.com> writes:
On 2015-05-03 23:28:00 +0000, anonymous said:

 You need to turn T into a parameter, so that StaticFilter can set it. 
 (And it's really a string again, so I'm renaming to s.)
 
 ----
 template startsNotWithp(string s)
 {
      enum startsNotWithp = startsNotWith!(s, 'p');
 }
 /* Shorthand syntax: enum startsNotWithp(string s) = startsNotWith!(s, 'p'); */
 ----
 
 alias rules = StaticFilter!(startsNotWithp, org_rules);
Hi, I have one more questions: Is it possible to write something like this? alias rules = StaticFilter!(startsNotWith(?, 'p'), org_rules); The ? should be used for every memember of org_rules. -- Robert M. Münch http://www.saphirion.com smarter | better | faster
May 04 2015
parent "anonymous" <anonymous example.com> writes:
On Monday, 4 May 2015 at 11:41:23 UTC, Robert M. Münch wrote:
 Hi, I have one more questions: Is it possible to write 
 something like this?

 alias rules = StaticFilter!(startsNotWith(?, 'p'), org_rules);

 The ? should be used for every memember of org_rules.
No, we don't have template literals.
May 04 2015
prev sibling parent "Per =?UTF-8?B?Tm9yZGzDtnci?= <per.nordlow gmail.com> writes:
 template startsNotWith(string s,char c){
     enum startsNotWith = s.length == 0 || s[0] != c;
 }
Better still: enum startsNotWith(string s, char c) = { return s.length == 0 || s[0] != c; }
May 06 2015
prev sibling next sibling parent "Dicebot" <public dicebot.lv> writes:
On Sunday, 3 May 2015 at 21:46:11 UTC, Robert M. Münch wrote:
 3. TupleType is a very missleading name when you are learning 
 these things, because the tuple can hold values as well. Or is 
 there a more extensive explanation for the name I don't get?
Legacy we are trying to get rid of. See also: https://github.com/D-Programming-Language/phobos/pull/3128 https://github.com/D-Programming-Language/dlang.org/pull/986
May 03 2015
prev sibling parent reply Rikki Cattermole <alphaglosined gmail.com> writes:
On 4/05/2015 9:46 a.m., Robert M. Münch wrote:
 Hi, I have now played a around couple of hours (reading everything I
 could find) to get something to work, but I think I'm missing some basic
 concepts/understanding. Maybe someone can enlighten me how these things
 work. I thought that some code from David Nadlinger is what I'm
 searching for but don't know how to exactly make use of it.

 Here is the code: I want to filter out some of the "allMembers" and use
 them in my code for a switch/final to check that call cases that were
 not filtered are covered. Trying to build the enum for the switch/final
 statement.

 auto org_rules = TypeTuple!(__traits(allMembers,BolSource));
 static assert(!isTypeTuple!(org_rules));

 template startsNotWith(T,char C){
     static if (T[0] != C){
         enum startsNotWith = true;
     } else {
         enum startsNotWith = false;
     }
 }

 template StaticFilter(alias pred, T...) {
   static if (T.length == 0) {
     alias TypeTuple!() StaticFilter;
   } else static if (pred!(T[0])) {
     alias TypeTuple!(T[0], StaticFilter!(pred, T[1 .. $])) StaticFilter;
   } else {
     alias StaticFilter!(pred, T[1 .. $]) StaticFilter;
   }
 }

 alias startsNotWithp = startsNotWith!(T,"p"); // doesn't compile: Error:
 undefined identifier T

 alias rules = StaticFilter!(startsNotWithp, org_rules);


 While playing with this a couple of questions came up:

 1. How do predicates get their argument(s)? I saw code where only the
 predicate was mentioned but no arguments. So, I assume there is some
 behind-the-curtain-magic going on. I read about things like "a == b"
 where I can reference 'a and 'b in a string.

 2. "enum startsNotwith = false" So this is the return syntax for a CTFE
 for "return(true)" ?

 3. TupleType is a very missleading name when you are learning these
 things, because the tuple can hold values as well. Or is there a more
 extensive explanation for the name I don't get?

 4. Are there any tutorials about CTFE? This seems to be a very powerful
 but not so easy to use feature of D, but documentation is quite limited.

 Thanks a lot.
Have you looked at my book? https://leanpub.com/ctfe
May 03 2015
next sibling parent reply =?iso-8859-1?Q?Robert_M._M=FCnch?= <robert.muench saphirion.com> writes:
On 2015-05-04 03:52:21 +0000, Rikki Cattermole said:

 Have you looked at my book? https://leanpub.com/ctfe
No, thanks for the hint. You will have one more reader ;-) -- Robert M. Münch http://www.saphirion.com smarter | better | faster
May 04 2015
parent Rikki Cattermole <alphaglosined gmail.com> writes:
On 4/05/2015 11:15 p.m., Robert M. Münch wrote:
 On 2015-05-04 03:52:21 +0000, Rikki Cattermole said:

 Have you looked at my book? https://leanpub.com/ctfe
No, thanks for the hint. You will have one more reader ;-)
I'm currently live streaming, feel free to jump on and ask any questions! https://www.livecoding.tv/alphaglosined/
May 04 2015
prev sibling parent reply =?iso-8859-1?Q?Robert_M._M=FCnch?= <robert.muench saphirion.com> writes:
On 2015-05-04 03:52:21 +0000, Rikki Cattermole said:

 Have you looked at my book? https://leanpub.com/ctfe
I bought it. Will it be updated? It's very generic with respect the concept and I'm missing code examples for all the user-cases. Especially the generator part is IMO very interesting. -- Robert M. Münch http://www.saphirion.com smarter | better | faster
May 04 2015
parent Rikki Cattermole <alphaglosined gmail.com> writes:
On 5/05/2015 6:24 a.m., Robert M. Münch wrote:
 On 2015-05-04 03:52:21 +0000, Rikki Cattermole said:

 Have you looked at my book? https://leanpub.com/ctfe
I bought it. Will it be updated? It's very generic with respect the concept and I'm missing code examples for all the user-cases. Especially the generator part is IMO very interesting.
It's due for an update. Basically I just need to be told what people want. Otherwise I'll be doing it blind!
May 04 2015