www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.announce - Metaprogramming in D : Some Real-world Examples

reply Walter Bright <newshound1 digitalmars.com> writes:
Looks like Bill Baxter is giving a presentation on D Nov. 18!

http://www.nwcpp.org/
Nov 09 2009
next sibling parent reply Bill Baxter <wbaxter gmail.com> writes:
On Mon, Nov 9, 2009 at 4:09 PM, Walter Bright
<newshound1 digitalmars.com> wrote:
 Looks like Bill Baxter is giving a presentation on D Nov. 18!

 http://www.nwcpp.org/
Yep, that's right, and I'd be quite grateful to you smart folks here if you could share your meta-programming favorites with me! If you've got a real-world example of meta-programming in D that you think is particularly handy, then please send it my way I'm looking for small-but-useful things that are easy to explain, and make something easier than it would be otherwise. Things like places where static if can save your butt, or loop unrolling, and passing code snippets to functions like in std.algorithm. Things like a compile-time raytracer or regexp parser (though quite cool!) are not what I'm after. Too involved for a short talk. --bb
Nov 09 2009
next sibling parent reply Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> writes:
Bill Baxter wrote:
 On Mon, Nov 9, 2009 at 4:09 PM, Walter Bright
 <newshound1 digitalmars.com> wrote:
 Looks like Bill Baxter is giving a presentation on D Nov. 18!

 http://www.nwcpp.org/
Yep, that's right, and I'd be quite grateful to you smart folks here if you could share your meta-programming favorites with me! If you've got a real-world example of meta-programming in D that you think is particularly handy, then please send it my way I'm looking for small-but-useful things that are easy to explain, and make something easier than it would be otherwise. Things like places where static if can save your butt, or loop unrolling, and passing code snippets to functions like in std.algorithm. Things like a compile-time raytracer or regexp parser (though quite cool!) are not what I'm after. Too involved for a short talk. --bb
std.random has code that checks the parameters of a congruential RNG during compilation. That's also an example in TDPL. Andrei
Nov 09 2009
parent reply Bill Baxter <wbaxter gmail.com> writes:
On Mon, Nov 9, 2009 at 6:03 PM, Andrei Alexandrescu
<SeeWebsiteForEmail erdani.org> wrote:
 Bill Baxter wrote:
 On Mon, Nov 9, 2009 at 4:09 PM, Walter Bright
 <newshound1 digitalmars.com> wrote:
 Looks like Bill Baxter is giving a presentation on D Nov. 18!

 http://www.nwcpp.org/
Yep, that's right, and I'd be quite grateful to you smart folks here if you could share your meta-programming favorites with me! =A0 If you've got a real-world example of meta-programming in D that you think is particularly handy, then please send it my way I'm looking for small-but-useful things that are easy to explain, and make something easier than it would be otherwise. =A0Things like places where static if can save your butt, =A0or loop unrolling, =A0and passing code snippets to functions like in std.algorithm. Things like a compile-time raytracer or regexp parser (though quite cool!) are not what I'm after. =A0Too involved for a short talk. --bb
std.random has code that checks the parameters of a congruential RNG duri=
ng
 compilation. That's also an example in TDPL.
This looks good. Any chance you could send me the snippet of the book that explains the rationale for what constitutes "proper linear congruential parameters"? --bb
Nov 12 2009
parent reply Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> writes:
Bill Baxter wrote:
 On Mon, Nov 9, 2009 at 6:03 PM, Andrei Alexandrescu
 <SeeWebsiteForEmail erdani.org> wrote:
 Bill Baxter wrote:
 On Mon, Nov 9, 2009 at 4:09 PM, Walter Bright
 <newshound1 digitalmars.com> wrote:
 Looks like Bill Baxter is giving a presentation on D Nov. 18!

 http://www.nwcpp.org/
Yep, that's right, and I'd be quite grateful to you smart folks here if you could share your meta-programming favorites with me! If you've got a real-world example of meta-programming in D that you think is particularly handy, then please send it my way I'm looking for small-but-useful things that are easy to explain, and make something easier than it would be otherwise. Things like places where static if can save your butt, or loop unrolling, and passing code snippets to functions like in std.algorithm. Things like a compile-time raytracer or regexp parser (though quite cool!) are not what I'm after. Too involved for a short talk. --bb
std.random has code that checks the parameters of a congruential RNG during compilation. That's also an example in TDPL.
This looks good. Any chance you could send me the snippet of the book that explains the rationale for what constitutes "proper linear congruential parameters"? --bb
It's been online for a while. http://erdani.com/tdpl/excerpt.pdf Andrei
Nov 12 2009
parent Bill Baxter <wbaxter gmail.com> writes:
On Thu, Nov 12, 2009 at 7:53 AM, Andrei Alexandrescu
<SeeWebsiteForEmail erdani.org> wrote:
 Bill Baxter wrote:
 On Mon, Nov 9, 2009 at 6:03 PM, Andrei Alexandrescu
 <SeeWebsiteForEmail erdani.org> wrote:
 Bill Baxter wrote:
 On Mon, Nov 9, 2009 at 4:09 PM, Walter Bright
 <newshound1 digitalmars.com> wrote:
 Looks like Bill Baxter is giving a presentation on D Nov. 18!

 http://www.nwcpp.org/
Yep, that's right, and I'd be quite grateful to you smart folks here if you could share your meta-programming favorites with me! =A0 If you've got a real-world example of meta-programming in D that you think is particularly handy, then please send it my way I'm looking for small-but-useful things that are easy to explain, and make something easier than it would be otherwise. =A0Things like place=
s
 where static if can save your butt, =A0or loop unrolling, =A0and passi=
ng
 code snippets to functions like in std.algorithm.

 Things like a compile-time raytracer or regexp parser (though quite
 cool!) are not what I'm after. =A0Too involved for a short talk.

 --bb
std.random has code that checks the parameters of a congruential RNG during compilation. That's also an example in TDPL.
This looks good. Any chance you could send me the snippet of the book that explains the rationale for what constitutes "proper linear congruential parameters"? --bb
It's been online for a while. http://erdani.com/tdpl/excerpt.pdf
Thanks, I guess I saw that at some point, but forgot what it contained. --bb
Nov 12 2009
prev sibling next sibling parent reply "Nick Sabalausky" <a a.a> writes:
"Bill Baxter" <wbaxter gmail.com> wrote in message 
news:mailman.290.1257812868.20261.digitalmars-d-announce puremagic.com...
 On Mon, Nov 9, 2009 at 4:09 PM, Walter Bright
 <newshound1 digitalmars.com> wrote:
 Looks like Bill Baxter is giving a presentation on D Nov. 18!

 http://www.nwcpp.org/
Yep, that's right, and I'd be quite grateful to you smart folks here if you could share your meta-programming favorites with me! If you've got a real-world example of meta-programming in D that you think is particularly handy, then please send it my way I'm looking for small-but-useful things that are easy to explain, and make something easier than it would be otherwise. Things like places where static if can save your butt, or loop unrolling, and passing code snippets to functions like in std.algorithm. Things like a compile-time raytracer or regexp parser (though quite cool!) are not what I'm after. Too involved for a short talk. --bb
I have a few things, mostly part of my SemiTwist D Tools project (http://www.dsource.org/projects/semitwist/): === Trace / Trace Value === Two of my personal favorites (particularly traceVal). Great for debugging. Implementation and Documentation (search for "trace" and "traceVal", implementations are less than 10 lines each): http://www.dsource.org/projects/semitwist/browser/trunk/src/semitwist/util/mixins.d Quick Example: ----------------------------- mixin(trace!()); mixin(trace!("--EASY TO VISUALLY GREP--")); int myVar=100; mixin(traceVal!("myVar ")); mixin(traceVal!("myVar-1")); mixin(traceVal!("min(4,7)", "max(4,7)")); ----------------------------- Output: ----------------------------- C:\path\file.d(1): trace --EASY TO VISUALLY GREP--: C:\path\file.d(3): trace myVar : 100 myVar-1: 99 min(4,7): 4 max(4,7): 7 ----------------------------- There's also a traceMixin that can be useful for debugging mixins (it'll replace a normal string mixin and echo at compile time via "pragma(msg, )" the string being mixed in). === Init Member === Great for DRY in constructors with many initialization parameters. Implementation and Documentation (at the top of the file): http://www.dsource.org/projects/semitwist/browser/trunk/src/semitwist/util/mixins.d Quick Example: ----------------------------- mixin(initMember!(someVar)); mixin(initMember!(a, b, c)); ----------------------------- Turns Into: ----------------------------- this.someVar = someVar; this.a = a; this.b = b; this.c = c; ----------------------------- Some variations are also available, such as initMemberFrom for copy constructors and initFrom copying class members to local vars. === Getters === DRY mixins for publicly read-only properties, and a "lazy" version for lazily computed & cached read-only properties. A poor replacement for a real DRY property syntax, but the next best thing. Implementation and Documentation (search for "getter" and "getterLazy"): http://www.dsource.org/projects/semitwist/browser/trunk/src/semitwist/util/mixins.d Quick Example: ----------------------------- // Third param optional mixin(getter!(float, "someFloat", 2.5)); mixin(getterLazy!(int, "myVar")); private int _myVar_gen() { // Ordinarily, this function would be much more complex // Also, any member func can set "_myVar_cached = false;" // to force this to be re-computed on the next request. return 7; } ----------------------------- Turns Into: ----------------------------- private float _someFloat = 2.5; private float someFloat(float _NEW_VAL_) { _someFloat = _NEW_VAL_; return _someFloat; } public float someFloat() { return _someFloat; } private int _myVar; private bool _myVar_cached = false; public int myVar() { if(!_myVar_cached) { _myVar_cached = true; _myVar = _myVar_gen(); } return _myVar; } private int _myVar_gen() { // Ordinarily, this function would be much more complex // Also, any member func can set "_myVar_cached = false;" // to force this to be re-computed on the next request. return 7; } ----------------------------- Variations are also available to use "protected" (or anything else) instead of private. === Defer Assert/Ensure === Uses metaprogramming to create an alternative to assert() that provides much of the usefulness of JUnit-style libs, but without the bulk of wrapping things like '==' and '||' in classes/structs or forcing unnatural syntax like '(a.equals(b)).or(c.notEquals(d))'. Also reports unexpected exceptions and allows requiring a particular exception to be thrown. Implemented in less than 200 lines, including blank lines and comments. Implementation: http://www.dsource.org/projects/semitwist/browser/trunk/src/semitwist/util/deferAssert.d Simple Test App: http://www.dsource.org/projects/semitwist/browser/trunk/src/semitwist/apps/tests/deferAssertTest/main.d Quick Example: ----------------------------- int foo = 2; mixin(deferAssert!(`foo == 3 || foo > 5`, "foo is bad")); mixin(deferEnsure!(`foo`, `_ == 3 || _ > 5`, "ensure foo failed")); flushAsserts(); ----------------------------- Output: ----------------------------- src\semitwist\apps\tests\deferAssertTest\main.d(37): Assert Failed (foo == 3 || foo > 5): foo is bad src\semitwist\apps\tests\deferAssertTest\main.d(42): Ensure Failed: ensure foo failed Expression 'foo': Expected: _ == 3 || _ > 5 Actual: 2 tango.core.Exception.AssertException src\semitwist\util\deferAssert.d(170): 2 Assert Failures ----------------------------- === Compile-time checking on types with non-identifier strings === Another of my favorites. This is from an upcoming release of my Goldie ( http://www.dsource.org/projects/goldie ) parser library. I have a class to represent a token, which could have any name like "+" or "Statement", etc., all depending on the user-defined grammar. Currently, this token name representation is dynamic/run-time, which is very flexible, but there's no compile-time checking of these names, which often a bad tradeoff because many programs that need to parse something already know (in fact, *must* already know) the token names, so the flexibility doesn't help them at all, but compile-time checking would. Unfortunately, the traditional approach to adding static checking would require every token name to be a valid identifier name, so for instance, "+" would have to be changed to "Plus", etc. And this can be problematic. It's extra work. It's very difficult to automate while getting good well-named results. It's possible (in a company setting, for instance) that the programmer might not be allowed or able to change the grammar. And of course, there's the possibility for name collisions (ie, what if "Plus" was already taken by another token?). Also, the new static class definition would probably need to be duplicated for each token. But all those problems can be solved in D quite easily with just a very small amount of some very simple metaprogramming. The actual implementation Goldie uses does get fairly involved, but the basic concept is dead simple. All it takes is one templated type paramater, one static if and one static assert (and the static if could easily be eliminated): ------------------------------------------------- // ----------- Dynamic Token ----------- // A Dynamic token. Flexible, but no compile-time checking class DynamicToken { protected char[] name; this(char[] name) { if(name != "+" && name != "Statement") throw new Exception("Invalid token: " ~ name); this.name = name; } // More Tokeny stuff here } unittest { auto t1 = new DynamicToken("+"); auto t2 = new DynamicToken("Statement"); auto t3 = new DynamicToken("Stment"); // Runtime error } // ----------- Old-Style Static Token ----------- class OldStyle_StaticToken_Statement : DynamicToken { this() { super("Statement"); } } // Note that "+" must be changed to "Plus", // Also, the whole class definition has to be repeated // (Although it's pretty small in this case.) class OldStyle_StaticToken_Plus : DynamicToken { this() { super("+"); } } unittest { // Supposed to be +, but had to be changed to Plus // by either the grammar author or by special complex // logic in the StaticToken-generation tool. // And if there was already another token actually named "Plus"... // Well, even more complexity arises. auto t1 = new OldStyle_StaticToken_Plus; auto t2 = new OldStyle_StaticToken_Statement; //auto t3 = new OldStyle_StaticToken_Stment; // Compile-time error } // ----------- New-Style Static Token ----------- class NewStyle_StaticToken(char[] staticName) : DynamicToken { static if(staticName != "+" && staticName != "Statement") static assert(false, "Invalid token: " ~ staticName); this() { super(staticName); } } unittest { auto t1 = new NewStyle_StaticToken!("+"); auto t2 = new NewStyle_StaticToken!("Statement"); //auto t3 = new NewStyle_StaticToken!("Stment"); // Compile-time error } -------------------------------------------------
Nov 09 2009
parent reply Bill Baxter <wbaxter gmail.com> writes:
Hi Nick,

Thanks for the response.  More below.

On Mon, Nov 9, 2009 at 6:46 PM, Nick Sabalausky <a a.a> wrote:
 "Bill Baxter" <wbaxter gmail.com> wrote in message
 news:mailman.290.1257812868.20261.digitalmars-d-announce puremagic.com...
 On Mon, Nov 9, 2009 at 4:09 PM, Walter Bright
 <newshound1 digitalmars.com> wrote:
I have a few things, mostly part of my SemiTwist D Tools project (http://www.dsource.org/projects/semitwist/): =3D=3D=3D Trace / Trace Value =3D=3D=3D Two of my personal favorites (particularly traceVal). Great for debugging=
.
 Implementation and Documentation (search for "trace" and "traceVal",
 implementations are less than 10 lines each):
 http://www.dsource.org/projects/semitwist/browser/trunk/src/semitwist/uti=
l/mixins.d
 Quick Example:
 -----------------------------
 mixin(trace!());
 mixin(trace!("--EASY TO VISUALLY GREP--"));

 int myVar=3D100;
 mixin(traceVal!("myVar =A0"));
 mixin(traceVal!("myVar-1"));
 mixin(traceVal!("min(4,7)", "max(4,7)"));
 -----------------------------

 Output:
 -----------------------------
 C:\path\file.d(1): trace
 --EASY TO VISUALLY GREP--: C:\path\file.d(3): trace
 myVar =A0: 100
 myVar-1: 99
 min(4,7): 4
 max(4,7): 7
 -----------------------------
This does, look handy, but the C++ equivalent based on preprocessor macros arguably looks better and has a simpler implementation: #define traceVal(x) cout << #x " : " << x; << endl; and to use just: traceVal(myVar); (assuming for a moment that c++ had a writefln) However, the unescape() function used in traceVal looks like it might be a useful CTFE example. Some kind of compile-time string escaping/unescaping could definitely be a good example.
 There's also a traceMixin that can be useful for debugging mixins (it'll
 replace a normal string mixin and echo at compile time via "pragma(msg, )=
"
 the string being mixed in).

 =3D=3D=3D Init Member =3D=3D=3D

 Great for DRY in constructors with many initialization parameters.

 Implementation and Documentation (at the top of the file):
 http://www.dsource.org/projects/semitwist/browser/trunk/src/semitwist/uti=
l/mixins.d
 Quick Example:
 -----------------------------
 mixin(initMember!(someVar));
 mixin(initMember!(a, b, c));
 -----------------------------

 Turns Into:
 -----------------------------
 this.someVar =3D someVar;
 this.a =3D a;
 this.b =3D b;
 this.c =3D c;
 -----------------------------

 Some variations are also available, such as initMemberFrom for copy
 constructors and initFrom copying class members to local vars.
I think I'd rather focus on examples that let you do something that would be difficult to do otherwise, rather than something that saves a bit of typing.
 =3D=3D=3D Getters =3D=3D=3D

 DRY mixins for publicly read-only properties, and a "lazy" version for
 lazily computed & cached read-only properties. A poor replacement for a r=
eal
 DRY property syntax, but the next best thing.

 Implementation and Documentation (search for "getter" and "getterLazy"):
 http://www.dsource.org/projects/semitwist/browser/trunk/src/semitwist/uti=
l/mixins.d
 Quick Example:
 -----------------------------
 // Third param optional
 mixin(getter!(float, "someFloat", 2.5));

 mixin(getterLazy!(int, "myVar"));
 private int _myVar_gen()
 {
 =A0 =A0// Ordinarily, this function would be much more complex
 =A0 =A0// Also, any member func can set "_myVar_cached =3D false;"
 =A0 =A0// to force this to be re-computed on the next request.
 =A0 =A0return 7;
 }
 -----------------------------


 Turns Into:
 -----------------------------
 private float _someFloat =3D 2.5;
 private float someFloat(float _NEW_VAL_)
 {
 =A0 =A0_someFloat =3D _NEW_VAL_;
 =A0 =A0return _someFloat;
 }
 public float someFloat()
 {
 =A0 =A0return _someFloat;
 }

 private int _myVar;
 private bool _myVar_cached =3D false;
 public int myVar() {
 =A0 =A0if(!_myVar_cached) {
 =A0 =A0 =A0 =A0_myVar_cached =3D true;
 =A0 =A0 =A0 =A0_myVar =3D _myVar_gen();
 =A0 =A0}
 =A0 =A0return _myVar;
 }
 private int _myVar_gen()
 {
 =A0 =A0// Ordinarily, this function would be much more complex
 =A0 =A0// Also, any member func can set "_myVar_cached =3D false;"
 =A0 =A0// to force this to be re-computed on the next request.
 =A0 =A0return 7;
 }
 -----------------------------

 Variations are also available to use "protected" (or anything else) inste=
ad
 of private.
This is more interesting than the last, but still falls pretty much in the "saves typing" category. Also I think it's arguable that these sacrifice some readablility to gain their terseness. For this sort of thing I'd rather have an IDE save me the typing, but actually create the code, instead of resorting to semi-cryptic naming conventions.
 =3D=3D=3D Defer Assert/Ensure =3D=3D=3D

 Uses metaprogramming to create an alternative to assert() that provides m=
uch
 of the usefulness of JUnit-style libs, but without the bulk of wrapping
 things like '=3D=3D' and '||' in classes/structs or forcing unnatural syn=
tax
 like '(a.equals(b)).or(c.notEquals(d))'. Also reports unexpected exceptio=
ns
 and allows requiring a particular exception to be thrown. Implemented in
 less than 200 lines, including blank lines and comments.

 Implementation:
 http://www.dsource.org/projects/semitwist/browser/trunk/src/semitwist/uti=
l/deferAssert.d
 Simple Test App:
 http://www.dsource.org/projects/semitwist/browser/trunk/src/semitwist/app=
s/tests/deferAssertTest/main.d
 Quick Example:
 -----------------------------
 int foo =3D 2;
 mixin(deferAssert!(`foo =3D=3D 3 || foo > 5`, "foo is bad"));
 mixin(deferEnsure!(`foo`, `_ =3D=3D 3 || _ > 5`, "ensure foo failed"));
 flushAsserts();
 -----------------------------

 Output:
 -----------------------------
 src\semitwist\apps\tests\deferAssertTest\main.d(37): Assert Failed (foo =
=3D=3D 3
 || foo > 5): foo is bad
 src\semitwist\apps\tests\deferAssertTest\main.d(42): Ensure Failed: ensur=
e
 foo failed
 Expression 'foo':
 Expected: _ =3D=3D 3 || _ > 5
 Actual: 2
 tango.core.Exception.AssertException src\semitwist\util\deferAssert.d(170=
):
 2 Assert Failures
 -----------------------------
This is another one that C++ people would just throw macros at and wonder what the big deal is.
 =3D=3D=3D Compile-time checking on types with non-identifier strings =3D=
=3D=3D
 Another of my favorites. This is from an upcoming release of my Goldie (
 http://www.dsource.org/projects/goldie ) parser library.

 I have a class to represent a token, which could have any name like "+" o=
r
 "Statement", etc., all depending on the user-defined grammar. Currently,
 this token name representation is dynamic/run-time, which is very flexibl=
e,
 but there's no compile-time checking of these names, which often a bad
 tradeoff because many programs that need to parse something already know =
(in
 fact, *must* already know) the token names, so the flexibility doesn't he=
lp
 them at all, but compile-time checking would.

 Unfortunately, the traditional approach to adding static checking would
 require every token name to be a valid identifier name, so for instance, =
"+"
 would have to be changed to "Plus", etc. And this can be problematic. It'=
s
 extra work. It's very difficult to automate while getting good well-named
 results. It's possible (in a company setting, for instance) that the
 programmer might not be allowed or able to change the grammar. And of
 course, there's the possibility for name collisions (ie, what if "Plus" w=
as
 already taken by another token?). Also, the new static class definition
 would probably need to be duplicated for each token. But all those proble=
ms
 can be solved in D quite easily with just a very small amount of some ver=
y
 simple metaprogramming.

 The actual implementation Goldie uses does get fairly involved, but the
 basic concept is dead simple. All it takes is one templated type paramate=
r,
 one static if and one static assert (and the static if could easily be
 eliminated):

 -------------------------------------------------
 // ----------- Dynamic Token -----------

 // A Dynamic token. Flexible, but no compile-time checking
 class DynamicToken
 {
 =A0 =A0protected char[] name;
 =A0 =A0this(char[] name)
 =A0 =A0{
 =A0 =A0 =A0 =A0if(name !=3D "+" && name !=3D "Statement")
 =A0 =A0 =A0 =A0 =A0 =A0throw new Exception("Invalid token: " ~ name);

 =A0 =A0 =A0 =A0this.name =3D name;
 =A0 =A0}
 =A0 =A0// More Tokeny stuff here
 }
 unittest
 {
 =A0 =A0auto t1 =3D new DynamicToken("+");
 =A0 =A0auto t2 =3D new DynamicToken("Statement");
 =A0 =A0auto t3 =3D new DynamicToken("Stment"); // Runtime error
 }

 // ----------- Old-Style Static Token -----------

 class OldStyle_StaticToken_Statement : DynamicToken
 {
 =A0 =A0this() { super("Statement"); }
 }
 // Note that "+" must be changed to "Plus",
 // Also, the whole class definition has to be repeated
 // (Although it's pretty small in this case.)
 class OldStyle_StaticToken_Plus : DynamicToken
 {
 =A0 =A0this() { super("+"); }
 }
 unittest
 {
 =A0 =A0// Supposed to be +, but had to be changed to Plus
 =A0 =A0// by either the grammar author or by special complex
 =A0 =A0// logic in the StaticToken-generation tool.
 =A0 =A0// And if there was already another token actually named "Plus"...
 =A0 =A0// Well, even more complexity arises.

 =A0 =A0auto t1 =3D new OldStyle_StaticToken_Plus;
 =A0 =A0auto t2 =3D new OldStyle_StaticToken_Statement;
 =A0 =A0//auto t3 =3D new OldStyle_StaticToken_Stment; // Compile-time err=
or
 }

 // ----------- New-Style Static Token -----------

 class NewStyle_StaticToken(char[] staticName) : DynamicToken
 {
 =A0 =A0static if(staticName !=3D "+" && staticName !=3D "Statement")
 =A0 =A0 =A0 =A0static assert(false, "Invalid token: " ~ staticName);

 =A0 =A0this() { super(staticName); }
 }
 unittest
 {
 =A0 =A0auto t1 =3D new NewStyle_StaticToken!("+");
 =A0 =A0auto t2 =3D new NewStyle_StaticToken!("Statement");
 =A0 =A0//auto t3 =3D new NewStyle_StaticToken!("Stment"); // Compile-time=
error
 }
 -------------------------------------------------
That is kinda neat, I suppose you could even extend that to make the list of valid tokens be a template parameter (either variadic, or separated by some delimiter in one big string that then gets broken up at runtime). I guess you could pitch this as a baby step towards the full-fledged compile-time parser. Step 0 recognize valid tokens. Thanks for writing all these up. --bb
Nov 12 2009
parent reply "Nick Sabalausky" <a a.a> writes:
"Bill Baxter" <wbaxter gmail.com> wrote in message 
news:mailman.337.1258023453.20261.digitalmars-d-announce puremagic.com...
Hi Nick,

Thanks for the response.  More below.

However, the unescape() function used in traceVal looks like it might
be a useful CTFE example.  Some kind of compile-time string
escaping/unescaping could definitely be a good example.
Heh, I tend to forget about that one. That's from the "semitwist.util.text" module, which I haven't worked with much in a long time, so there's probably a lot of WTFs spread through the module, and if you use something there as an example, you might need to clean it up a little. FWIW, that double-quote-string escaping/unescaping is built around ctfe_substitute which is in "semitwist.util.ctfe" (although Tango might have something similar by now).
 [various]
This is another one that C++ people would just throw macros at and wonder what the big deal is.
Ah, yea, good point. Of course, we'd probably all take D's metaprogramming over preprocessor macros anyday, but I can definitely see their point.
 === Compile-time checking on types with non-identifier strings ===
That is kinda neat, I suppose you could even extend that to make the list of valid tokens be a template parameter (either variadic, or separated by some delimiter in one big string that then gets broken up at runtime). I guess you could pitch this as a baby step towards the full-fledged compile-time parser. Step 0 recognize valid tokens.
Interesting idea, yea. Might not be much help for the lib as I currently have it though, since I'm just spitting out the static-style language definitions from a tool that takes in a grammar and generates D code. Certainly something to keep in mind for future expansion though.
Thanks for writing all these up.
No prob! :)
Nov 12 2009
parent "Nick Sabalausky" <a a.a> writes:
"Nick Sabalausky" <a a.a> wrote in message 
news:hdgt9q$vti$1 digitalmars.com...
"Bill Baxter" <wbaxter gmail.com> wrote in message 
news:mailman.337.1258023453.20261.digitalmars-d-announce puremagic.com...
Hi Nick,
 === Compile-time checking on types with non-identifier strings ===
That is kinda neat, I suppose you could even extend that to make the list of valid tokens be a template parameter (either variadic, or separated by some delimiter in one big string that then gets broken up at runtime). I guess you could pitch this as a baby step towards the full-fledged compile-time parser. Step 0 recognize valid tokens.
Interesting idea, yea. Might not be much help for the lib as I currently have it though, since I'm just spitting out the static-style language definitions from a tool that takes in a grammar and generates D code. Certainly something to keep in mind for future expansion though.
One other idea I had for expanding on that NewStyle_StaticToken would be: Suppose a grammar had some sort of naming convention that, well, meant something within the context of that grammar. Then the application code could take something like "process(Token!("foo") token) {...}" and use compile-time string processing to do advanced pattern-matching on the token-name when selecting which token types to process a certain way (maybe it would have to be a static if or a templated instead of a basic function though). Not a fully fleshed-out idea, of course, but maybe the start of something. In fact, I think tango.util.Convert does something vaguely like that to look for conversion functions.
Nov 12 2009
prev sibling next sibling parent reply "Denis Koroskin" <2korden gmail.com> writes:
On Tue, 10 Nov 2009 03:27:20 +0300, Bill Baxter <wbaxter gmail.com> wrote:

 On Mon, Nov 9, 2009 at 4:09 PM, Walter Bright
 <newshound1 digitalmars.com> wrote:
 Looks like Bill Baxter is giving a presentation on D Nov. 18!

 http://www.nwcpp.org/
Yep, that's right, and I'd be quite grateful to you smart folks here if you could share your meta-programming favorites with me! If you've got a real-world example of meta-programming in D that you think is particularly handy, then please send it my way I'm looking for small-but-useful things that are easy to explain, and make something easier than it would be otherwise. Things like places where static if can save your butt, or loop unrolling, and passing code snippets to functions like in std.algorithm. Things like a compile-time raytracer or regexp parser (though quite cool!) are not what I'm after. Too involved for a short talk. --bb
kprintf (a printf variant) in XoMB is a nice example imo. It accepts format as a template parameter, doing all the checks at compile-time (and more). http://github.com/xomboverlord/xomb-bare-bones/blob/6d924a9fd7cafe43aa50f38c0cd04c44187d4993/kernel/core/kprintf.d /* This template will generate code for printing and will do * all parsing of the format string at compile time * * USAGE: * kprintf!("format string {specifier} ... ")(args...); * * EXAMPLES: * kprintf!("Integer: {}")(10); * kprintf!("{!cls}Cleared the screen.")(); * kprintf!("{!pos:2,3}At position (2,3)")(); * kprintf!("{!fg:LightBlue!bg:Gray}{}")(25); * kprintf!("{!fg:Red}redness")(); * kprintf!("{x} Hex!")(145); * kprintf!("Curly Brace: {{")(); * * COMMANDS: * !cls - Clears the screen. * !fg - Sets the foreground color, see the Color enum * in kernel/dev/console.d. * !bg - Sets the background color, same as above. * !pos - Moves the cursor to the x and y given, see example above. * * SPECIFIERS: * {x} - Prints the hex value. * {u} - Treats as unsigned. * {} - Prints common form. * * WHY IS IT COOL? * - Compile time parsing of format strings * - Type checking at compile time as well * - That means it can tell you that you are dumb before you execute. * - No need to specify type information. * * - So we can do this and not care about the * output of the function: * * auto blah = someFunction(); * kprintf!("Some Arbitrary Info: {}")(blah); * * WOWWY WOW WOW! * */
Nov 10 2009
parent Bill Baxter <wbaxter gmail.com> writes:
2009/11/10 Denis Koroskin <2korden gmail.com>:
 On Tue, 10 Nov 2009 03:27:20 +0300, Bill Baxter <wbaxter gmail.com> wrote:

 kprintf (a printf variant) in XoMB is a nice example imo. It accepts format
 as a template parameter, doing all the checks at compile-time (and more).

 http://github.com/xomboverlord/xomb-bare-bones/blob/6d924a9fd7cafe43aa50f38c0cd04c44187d4993/kernel/core/kprintf.d
Nice. 400 lines is a little long for this purpose, though. Maybe a somewhat simplified version that just replaces {} with template args would be good. I guess that's pretty much what std.metastrings.Format does, just with %s instead of {}. --bb
Nov 12 2009
prev sibling next sibling parent reply Lutger <lutger.blijdestijn gmail.com> writes:
Bill Baxter wrote:

 On Mon, Nov 9, 2009 at 4:09 PM, Walter Bright
 <newshound1 digitalmars.com> wrote:
 Looks like Bill Baxter is giving a presentation on D Nov. 18!

 http://www.nwcpp.org/
Yep, that's right, and I'd be quite grateful to you smart folks here if you could share your meta-programming favorites with me! If you've got a real-world example of meta-programming in D that you think is particularly handy, then please send it my way I'm looking for small-but-useful things that are easy to explain, and make something easier than it would be otherwise. Things like places where static if can save your butt, or loop unrolling, and passing code snippets to functions like in std.algorithm. Things like a compile-time raytracer or regexp parser (though quite cool!) are not what I'm after. Too involved for a short talk. --bb
Great, I hope to see some slides or a video! Here is a watered down example of what I currently use to help with the boilerplate code of a visitor. It doesn't look much, but it's helpful when you have lots of visitable classes and in case of adding new classes. The code should run as is: import std.stdio; enum Visitable = q{ override void accept(IVisitor visitor) { visitor.visit(this); } }; interface IExpression { void accept(IVisitor visitor); } class Sum : IExpression { mixin(Visitable); } class Product : IExpression { mixin(Visitable); } string visitMethodOf(string type) { return "void visit(" ~ type ~ ");"; } string FoldStringsOf(alias F)(string[] list) { string result = ""; foreach (element ; list) result ~= F(element); return result; } interface IVisitor { mixin( FoldStringsOf!visitMethodOf( ["Sum", "Product"] ) ); } class Visitor : IVisitor { void visit(Sum node) { writeln("sum"); } void visit(Product node) { writeln("product"); } } void main() { auto printer = new Visitor(); IExpression sum = new Sum(); IExpression product = new Product(); sum.accept(printer); product.accept(printer); }
Nov 10 2009
parent reply Bill Baxter <wbaxter gmail.com> writes:
On Tue, Nov 10, 2009 at 3:32 AM, Lutger <lutger.blijdestijn gmail.com> wrot=
e:
 Bill Baxter wrote:

 On Mon, Nov 9, 2009 at 4:09 PM, Walter Bright
 <newshound1 digitalmars.com> wrote:
 Looks like Bill Baxter is giving a presentation on D Nov. 18!

 http://www.nwcpp.org/
Yep, that's right, and I'd be quite grateful to you smart folks here if you could share your meta-programming favorites with me! =A0 If you've got a real-world example of meta-programming in D that you think is particularly handy, then please send it my way I'm looking for small-but-useful things that are easy to explain, and make something easier than it would be otherwise. =A0Things like places where static if can save your butt, =A0or loop unrolling, =A0and passing code snippets to functions like in std.algorithm. Things like a compile-time raytracer or regexp parser (though quite cool!) are not what I'm after. =A0Too involved for a short talk. --bb
Great, I hope to see some slides or a video! Here is a watered down example of what I currently use to help with the boilerplate code of a visitor. It doesn't look much, but it's helpful whe=
n
 you have lots of visitable classes and in case of adding new classes. The
 code should run as is:

 import std.stdio;

 enum Visitable =3D
 q{
 =A0 =A0override void accept(IVisitor visitor)
 =A0 =A0{
 =A0 =A0 =A0 =A0visitor.visit(this);
 =A0 =A0}
 };

 interface IExpression
 {
 =A0 =A0void accept(IVisitor visitor);
 }

 class Sum : IExpression
 {
 =A0 =A0mixin(Visitable);
 }

 class Product : IExpression
 {
 =A0 =A0mixin(Visitable);
 }

 string visitMethodOf(string type)
 {
 =A0 =A0return "void visit(" ~ type ~ ");";
 }

 string FoldStringsOf(alias F)(string[] list)
 {
 =A0 =A0string result =3D "";
 =A0 =A0foreach (element ; list)
 =A0 =A0 =A0 =A0result ~=3D F(element);
 =A0 =A0return result;
 }

 interface IVisitor
 {
 =A0 =A0mixin( FoldStringsOf!visitMethodOf( ["Sum", "Product"] ) );
 }

 class Visitor : IVisitor
 {
 =A0 =A0void visit(Sum node)
 =A0 =A0{
 =A0 =A0 =A0 =A0writeln("sum");
 =A0 =A0}

 =A0 =A0void visit(Product node)
 =A0 =A0{
 =A0 =A0 =A0 =A0writeln("product");
 =A0 =A0}
 }

 void main()
 {
 =A0 =A0auto printer =3D new Visitor();

 =A0 =A0IExpression sum =3D new Sum();
 =A0 =A0IExpression product =3D new Product();

 =A0 =A0sum.accept(printer);
 =A0 =A0product.accept(printer);
 }
This is almost just a preprocessor macro trick, except for this line: mixin( FoldStringsOf!visitMethodOf( ["Sum", "Product"] ) ); The essence is to generate a bunch of methods from a list of names. I was thinking to include a similar example from the world of 3d graphics, which is generating all the swizzles of a vector* (got the idea from Tom S.). That's got the method generation from a list, but it also generates the list too. Another way is to have a swizz member template that lets you do v.swiz("zyx"). That's arguably better in that you don't pay for it if you don't use it. But being able to generate all the methods with D is still kinda spiffy. * Most GPU languages (HLSL,glsl,Cg) have a swizzle syntax, such that for a float3 v; v.zyx gives you float3(v.z,v.y,v.x). And this works for all suffixes. v.xxx, v.xzy, etc. Also for different numbers of components. eg. v.xz is float2(v.x,v.z). --bb
Nov 12 2009
parent Lutger <lutger.blijdestijn gmail.com> writes:
Bill Baxter wrote:

...
 
 This is almost just a preprocessor macro trick, except for this line:
      mixin( FoldStringsOf!visitMethodOf( ["Sum", "Product"] ) );
 
 The essence is to generate a bunch of methods from a list of names.  I
 was thinking to include a similar example from the world of 3d
 graphics, which is generating all the swizzles of a vector* (got the
 idea from Tom S.).  That's got the method generation from a list, but
 it also generates the list too.
Interesting. I noticed it's also possible to pass a module as an alias and to things with it, but haven't come across an example of where that would be used. Modules are almost something in D, but just not yet.
 Another way is to have a swizz member template that lets you do
 v.swiz("zyx").  That's arguably better in that you don't pay for it if
 you don't use it.  But being able to generate all the methods with D
 is still kinda spiffy.
 
 * Most GPU languages (HLSL,glsl,Cg) have a swizzle syntax, such that
 for a float3 v;   v.zyx  gives you float3(v.z,v.y,v.x).  And this
 works for all suffixes.   v.xxx, v.xzy, etc.  Also for different
 numbers of components.   eg.  v.xz is float2(v.x,v.z).
 
 --bb
swizzling is a neat example! I also have code that actually implements the visitor interface with stubs that print, throw or assert, but it's kind of hairy.
Nov 12 2009
prev sibling next sibling parent reply Jacob Carlborg <doob me.com> writes:
On 11/10/09 01:27, Bill Baxter wrote:
 On Mon, Nov 9, 2009 at 4:09 PM, Walter Bright
 <newshound1 digitalmars.com>  wrote:
 Looks like Bill Baxter is giving a presentation on D Nov. 18!

 http://www.nwcpp.org/
Yep, that's right, and I'd be quite grateful to you smart folks here if you could share your meta-programming favorites with me! If you've got a real-world example of meta-programming in D that you think is particularly handy, then please send it my way I'm looking for small-but-useful things that are easy to explain, and make something easier than it would be otherwise. Things like places where static if can save your butt, or loop unrolling, and passing code snippets to functions like in std.algorithm. Things like a compile-time raytracer or regexp parser (though quite cool!) are not what I'm after. Too involved for a short talk. --bb
This is invaluable to me, which makes it possible to do some form of duck typing at compile time: static if (is(typeof({ /* does this compile */ }))) Then I have some other things, not the most useful stuff but still usable: Get the name of a function Get the parameter names of a function Get the field names of a class/struct Get/set private fields of a class/struct outside the module Call a function with named arguments Then some templates that check if a type has a (class) method
Nov 10 2009
parent reply "Lars T. Kyllingstad" <public kyllingen.NOSPAMnet> writes:
Jacob Carlborg wrote:
 On 11/10/09 01:27, Bill Baxter wrote:
 On Mon, Nov 9, 2009 at 4:09 PM, Walter Bright
 <newshound1 digitalmars.com>  wrote:
 Looks like Bill Baxter is giving a presentation on D Nov. 18!

 http://www.nwcpp.org/
Yep, that's right, and I'd be quite grateful to you smart folks here if you could share your meta-programming favorites with me! If you've got a real-world example of meta-programming in D that you think is particularly handy, then please send it my way I'm looking for small-but-useful things that are easy to explain, and make something easier than it would be otherwise. Things like places where static if can save your butt, or loop unrolling, and passing code snippets to functions like in std.algorithm. Things like a compile-time raytracer or regexp parser (though quite cool!) are not what I'm after. Too involved for a short talk. --bb
This is invaluable to me, which makes it possible to do some form of duck typing at compile time: static if (is(typeof({ /* does this compile */ })))
There are forces at work (Don, that is) attempting to get rid of that very construct and replace it with something better: http://www.digitalmars.com/d/archives/digitalmars/D/Proposal_Replace_traits_and_is_typeof_XXX_with_a_magic_namespace_._99914.html In my humble opinion, is(typeof({...})) is an ugly creature. I really don't think it should be put under a spotlight as a good example of D metaprogramming. If anything, please use __traits(compiles, {...}) instead. -Lars
Nov 10 2009
next sibling parent Jacob Carlborg <doob me.com> writes:
On 11/10/09 13:29, Lars T. Kyllingstad wrote:
 Jacob Carlborg wrote:
 On 11/10/09 01:27, Bill Baxter wrote:
 On Mon, Nov 9, 2009 at 4:09 PM, Walter Bright
 <newshound1 digitalmars.com> wrote:
 Looks like Bill Baxter is giving a presentation on D Nov. 18!

 http://www.nwcpp.org/
Yep, that's right, and I'd be quite grateful to you smart folks here if you could share your meta-programming favorites with me! If you've got a real-world example of meta-programming in D that you think is particularly handy, then please send it my way I'm looking for small-but-useful things that are easy to explain, and make something easier than it would be otherwise. Things like places where static if can save your butt, or loop unrolling, and passing code snippets to functions like in std.algorithm. Things like a compile-time raytracer or regexp parser (though quite cool!) are not what I'm after. Too involved for a short talk. --bb
This is invaluable to me, which makes it possible to do some form of duck typing at compile time: static if (is(typeof({ /* does this compile */ })))
There are forces at work (Don, that is) attempting to get rid of that very construct and replace it with something better: http://www.digitalmars.com/d/archives/digitalmars/D/Proposal_Replace_traits_and_is_typeof_XXX_with_a_magic_namespace_._99914.html In my humble opinion, is(typeof({...})) is an ugly creature. I really don't think it should be put under a spotlight as a good example of D metaprogramming. If anything, please use __traits(compiles, {...}) instead. -Lars
Yes, it's very ugly. As long as the functionality is left in the language I'm happy. I'm using D1 where __traits isn't available.
Nov 10 2009
prev sibling next sibling parent Bill Baxter <wbaxter gmail.com> writes:
On Tue, Nov 10, 2009 at 4:29 AM, Lars T. Kyllingstad
<public kyllingen.nospamnet> wrote:
 Jacob Carlborg wrote:
 On 11/10/09 01:27, Bill Baxter wrote:
 On Mon, Nov 9, 2009 at 4:09 PM, Walter Bright
 <newshound1 digitalmars.com> =A0wrote:
 Looks like Bill Baxter is giving a presentation on D Nov. 18!

 http://www.nwcpp.org/
Yep, that's right, and I'd be quite grateful to you smart folks here if you could share your meta-programming favorites with me! =A0 If you've got a real-world example of meta-programming in D that you think is particularly handy, then please send it my way I'm looking for small-but-useful things that are easy to explain, and make something easier than it would be otherwise. =A0Things like places where static if can save your butt, =A0or loop unrolling, =A0and passin=
g
 code snippets to functions like in std.algorithm.

 Things like a compile-time raytracer or regexp parser (though quite
 cool!) are not what I'm after. =A0Too involved for a short talk.

 --bb
This is invaluable to me, which makes it possible to do some form of duc=
k
 typing at compile time:

 static if (is(typeof({
 /* does this compile */
 })))
There are forces at work (Don, that is) attempting to get rid of that ver=
y
 construct and replace it with something better:

 http://www.digitalmars.com/d/archives/digitalmars/D/Proposal_Replace_trai=
ts_and_is_typeof_XXX_with_a_magic_namespace_._99914.html
 In my humble opinion, is(typeof({...})) is an ugly creature. I really don=
't
 think it should be put under a spotlight as a good example of D
 metaprogramming. If anything, please use __traits(compiles, {...}) instea=
d. I really liked the meta.compiles(...) or meta(compiles, ...) idea. You're right though. I would rather show things that look deliberately designed to do the job nicely instead of things that look like hacks. Unfortunately, a lot of "real-world" D meta-programming currently requires hacky-looking things. So I can't really avoid them all. --bb
Nov 10 2009
prev sibling parent reply grauzone <none example.net> writes:
Lars T. Kyllingstad wrote:
 Jacob Carlborg wrote:
 On 11/10/09 01:27, Bill Baxter wrote:
 On Mon, Nov 9, 2009 at 4:09 PM, Walter Bright
 <newshound1 digitalmars.com>  wrote:
 Looks like Bill Baxter is giving a presentation on D Nov. 18!

 http://www.nwcpp.org/
Yep, that's right, and I'd be quite grateful to you smart folks here if you could share your meta-programming favorites with me! If you've got a real-world example of meta-programming in D that you think is particularly handy, then please send it my way I'm looking for small-but-useful things that are easy to explain, and make something easier than it would be otherwise. Things like places where static if can save your butt, or loop unrolling, and passing code snippets to functions like in std.algorithm. Things like a compile-time raytracer or regexp parser (though quite cool!) are not what I'm after. Too involved for a short talk. --bb
This is invaluable to me, which makes it possible to do some form of duck typing at compile time: static if (is(typeof({ /* does this compile */ })))
There are forces at work (Don, that is) attempting to get rid of that very construct and replace it with something better: http://www.digitalmars.com/d/archives/digitalmars/D/Proposal_Replace_traits_and_is_typeof_XXX_with_a_magic_na espace_._99914.html In my humble opinion, is(typeof({...})) is an ugly creature. I really don't think it should be put under a spotlight as a good example of D metaprogramming. If anything, please use __traits(compiles, {...}) instead.
Who cares about "ugly" syntax, if the idea is bad in the first place?
 -Lars
Nov 10 2009
parent reply Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> writes:
grauzone wrote:
 Lars T. Kyllingstad wrote:
 Jacob Carlborg wrote:
 On 11/10/09 01:27, Bill Baxter wrote:
 On Mon, Nov 9, 2009 at 4:09 PM, Walter Bright
 <newshound1 digitalmars.com>  wrote:
 Looks like Bill Baxter is giving a presentation on D Nov. 18!

 http://www.nwcpp.org/
Yep, that's right, and I'd be quite grateful to you smart folks here if you could share your meta-programming favorites with me! If you've got a real-world example of meta-programming in D that you think is particularly handy, then please send it my way I'm looking for small-but-useful things that are easy to explain, and make something easier than it would be otherwise. Things like places where static if can save your butt, or loop unrolling, and passing code snippets to functions like in std.algorithm. Things like a compile-time raytracer or regexp parser (though quite cool!) are not what I'm after. Too involved for a short talk. --bb
This is invaluable to me, which makes it possible to do some form of duck typing at compile time: static if (is(typeof({ /* does this compile */ })))
There are forces at work (Don, that is) attempting to get rid of that very construct and replace it with something better: http://www.digitalmars.com/d/archives/digitalmars/D/Proposal_Replace_traits_and_is_typeof_XXX_with_a_magic_na espace_._99914.html In my humble opinion, is(typeof({...})) is an ugly creature. I really don't think it should be put under a spotlight as a good example of D metaprogramming. If anything, please use __traits(compiles, {...}) instead.
Who cares about "ugly" syntax, if the idea is bad in the first place?
I think testing types during compilation isn't bad. Under what circumstances is it? Andrei
Nov 10 2009
parent reply grauzone <none example.net> writes:
Andrei Alexandrescu wrote:
 grauzone wrote:
 Lars T. Kyllingstad wrote:
 Jacob Carlborg wrote:
 On 11/10/09 01:27, Bill Baxter wrote:
 On Mon, Nov 9, 2009 at 4:09 PM, Walter Bright
 <newshound1 digitalmars.com>  wrote:
 Looks like Bill Baxter is giving a presentation on D Nov. 18!

 http://www.nwcpp.org/
Yep, that's right, and I'd be quite grateful to you smart folks here if you could share your meta-programming favorites with me! If you've got a real-world example of meta-programming in D that you think is particularly handy, then please send it my way I'm looking for small-but-useful things that are easy to explain, and make something easier than it would be otherwise. Things like places where static if can save your butt, or loop unrolling, and passing code snippets to functions like in std.algorithm. Things like a compile-time raytracer or regexp parser (though quite cool!) are not what I'm after. Too involved for a short talk. --bb
This is invaluable to me, which makes it possible to do some form of duck typing at compile time: static if (is(typeof({ /* does this compile */ })))
There are forces at work (Don, that is) attempting to get rid of that very construct and replace it with something better: http://www.digitalmars.com/d/archives/digitalmars/D/Proposal_Replace_traits_and_is_typeof_XXX_with_a_magic_na espace_._99914.html In my humble opinion, is(typeof({...})) is an ugly creature. I really don't think it should be put under a spotlight as a good example of D metaprogramming. If anything, please use __traits(compiles, {...}) instead.
Who cares about "ugly" syntax, if the idea is bad in the first place?
I think testing types during compilation isn't bad. Under what circumstances is it?
You're not testing for types, you're testing if it compiles. Inside the tested block of code, all sorts of things could go wrong. You can't know if is(typeof(...)) really did what you wanted, or if something broke. At least when you're doing more complex stuff with is(typeof), the danger of silent failures increases. Suppose the user makes an error in his custom range type by specifying a wrong return type (or whatever), and the range library just ignores his range-related function. Maybe that range function was optional, which will end in the range library seemingly ignoring his function. Can this be good? (I don't know if that case I described can even happen in your ranges lib, but I think this is a typical failure that could happen with is(typeof).) This isn't even compiletime duck typing anymore, it's try-and-error built into the compiler. Even worse, now having semantically incorrect code in D sources is perfectly fine for weird reasons, and the compiler has to "swallow" some kinds of semantics errors. Really, wouldn't some mechanism to explicitly check for compile time contracts better? For me, this is some sort of metaprogramming WTF. This all makes me cringe. Sorry about that.
 Andrei
Nov 11 2009
parent reply Christopher Wright <dhasenan gmail.com> writes:
grauzone wrote:
 You're not testing for types, you're testing if it compiles. Inside the 
 tested block of code, all sorts of things could go wrong. You can't know 
 if is(typeof(...)) really did what you wanted, or if something broke.
So it requires caution, and you want to keep the contents small. It's useful, but it requires caution.
Nov 11 2009
parent reply Don <nospam nospam.com> writes:
Christopher Wright wrote:
 grauzone wrote:
 You're not testing for types, you're testing if it compiles. Inside 
 the tested block of code, all sorts of things could go wrong. You 
 can't know if is(typeof(...)) really did what you wanted, or if 
 something broke.
You're testing, "is everything inside that OK?". If you want to know WHY it's wrong, you'd better make sure you're testing something simple.
 So it requires caution, and you want to keep the contents small. It's 
 useful, but it requires caution.
I don't even think it particularly requires caution. If it passes, you know everything is OK. It's just that it's an all-or-nothing test. IMHO, one of the best features of it, is that you can have negative compile-time unit tests. You can create tests which must be rejected at compile time. I don't know of any other clean way to do that.
Nov 11 2009
parent reply grauzone <none example.net> writes:
Don wrote:
 Christopher Wright wrote:
 grauzone wrote:
 You're not testing for types, you're testing if it compiles. Inside 
 the tested block of code, all sorts of things could go wrong. You 
 can't know if is(typeof(...)) really did what you wanted, or if 
 something broke.
You're testing, "is everything inside that OK?". If you want to know WHY it's wrong, you'd better make sure you're testing something simple.
Andrei's range lib uses it more in a way "does this type support this and that range interface?". Example: http://dsource.org/projects/phobos/browser/trunk/phobos/std/range.d#L58
 So it requires caution, and you want to keep the contents small. It's 
 useful, but it requires caution.
I don't even think it particularly requires caution. If it passes, you know everything is OK. It's just that it's an all-or-nothing test.
And if it doesn't pass, you know something is not ok? Then shouldn't you raise an error? Oh wait...
 IMHO, one of the best features of it, is that you can have negative 
 compile-time unit tests. You can create tests which must be rejected at 
 compile time. I don't know of any other clean way to do that.
True; that's another use of this feature.
Nov 11 2009
next sibling parent reply Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> writes:
grauzone wrote:
 Don wrote:
 Christopher Wright wrote:
 grauzone wrote:
 You're not testing for types, you're testing if it compiles. Inside 
 the tested block of code, all sorts of things could go wrong. You 
 can't know if is(typeof(...)) really did what you wanted, or if 
 something broke.
You're testing, "is everything inside that OK?". If you want to know WHY it's wrong, you'd better make sure you're testing something simple.
Andrei's range lib uses it more in a way "does this type support this and that range interface?". Example: http://dsource.org/projects/phobos/browser/trunk/phobos/std/range.d#L58
Then different isXxxRange are used by higher-order ranges in defining refined interfaces depending on the interfaces offered by their inputs. I fail to see how that's terrible. I am very happy D has that feature - no other statically-typed language has it, and it can be used to great effect. Look e.g. at Chain: http://dsource.org/projects/phobos/browser/trunk/phobos/std/range.d#L799 There, the uses of static if (is(...)) allow Chain to define as capable an interface as its inputs allow. Andrei
Nov 11 2009
next sibling parent reply grauzone <none example.net> writes:
Andrei Alexandrescu wrote:
 grauzone wrote:
 Don wrote:
 Christopher Wright wrote:
 grauzone wrote:
 You're not testing for types, you're testing if it compiles. Inside 
 the tested block of code, all sorts of things could go wrong. You 
 can't know if is(typeof(...)) really did what you wanted, or if 
 something broke.
You're testing, "is everything inside that OK?". If you want to know WHY it's wrong, you'd better make sure you're testing something simple.
Andrei's range lib uses it more in a way "does this type support this and that range interface?". Example: http://dsource.org/projects/phobos/browser/trunk/phobos/std/range.d#L58
Then different isXxxRange are used by higher-order ranges in defining refined interfaces depending on the interfaces offered by their inputs.
That means if one isXxxRange fails because the user maybe made a typo in the needed range function, the code will silently do something else. But my main problem is that the user just gets a "does not match template declaration" compiler error when he messes up his range interface. He's neither told that e.g. his range-related function returns the wrong type, nor is there any other refined error message. Now what if we'd introduce some sort of interfaces for type checking at compile time? interface InputRange(T) { void popFront(); bool empty(); T front(); } struct MyRange : InputRange!(int) { void popFront() { ... } //compiler error goes here... void empty() { ... } int front() { ... } } (or something like this) PS: there are two aspects to the problem: 1. even compile time duck typing shares some of the problems of runtime duck typing, and 2. utterly unhelpful error messages. If you wouldn't explicitly check the interface with is(typeof()), the compiler's error messages would be even worse because of 1.
 I fail to see how that's terrible. I am very happy D has that feature - 
 no other statically-typed language has it, and it can be used to great 
 effect. Look e.g. at Chain:
 
 http://dsource.org/projects/phobos/browser/trunk/phobos/std/range.d#L799
 
 There, the uses of static if (is(...)) allow Chain to define as capable 
 an interface as its inputs allow.
 
 
 Andrei
Nov 11 2009
parent Jacob Carlborg <doob me.com> writes:
On 11/11/09 17:58, grauzone wrote:
 Andrei Alexandrescu wrote:
 grauzone wrote:
 Don wrote:
 Christopher Wright wrote:
 grauzone wrote:
 You're not testing for types, you're testing if it compiles.
 Inside the tested block of code, all sorts of things could go
 wrong. You can't know if is(typeof(...)) really did what you
 wanted, or if something broke.
You're testing, "is everything inside that OK?". If you want to know WHY it's wrong, you'd better make sure you're testing something simple.
Andrei's range lib uses it more in a way "does this type support this and that range interface?". Example: http://dsource.org/projects/phobos/browser/trunk/phobos/std/range.d#L58
Then different isXxxRange are used by higher-order ranges in defining refined interfaces depending on the interfaces offered by their inputs.
That means if one isXxxRange fails because the user maybe made a typo in the needed range function, the code will silently do something else. But my main problem is that the user just gets a "does not match template declaration" compiler error when he messes up his range interface. He's neither told that e.g. his range-related function returns the wrong type, nor is there any other refined error message.
The check doesn't have to look like that. The check can be inside the template with static if and you can have several checks for different things and use static assert to output a error message that make sense.
 Now what if we'd introduce some sort of interfaces for type checking at
 compile time?

 interface InputRange(T) {
 void popFront();
 bool empty();
 T front();
 }

 struct MyRange : InputRange!(int) {
 void popFront() { ... }

 //compiler error goes here...
 void empty() { ... }

 int front() { ... }
 }

 (or something like this)

 PS: there are two aspects to the problem: 1. even compile time duck
 typing shares some of the problems of runtime duck typing, and 2.
 utterly unhelpful error messages. If you wouldn't explicitly check the
 interface with is(typeof()), the compiler's error messages would be even
 worse because of 1.

 I fail to see how that's terrible. I am very happy D has that feature
 - no other statically-typed language has it, and it can be used to
 great effect. Look e.g. at Chain:

 http://dsource.org/projects/phobos/browser/trunk/phobos/std/range.d#L799

 There, the uses of static if (is(...)) allow Chain to define as
 capable an interface as its inputs allow.


 Andrei
Nov 12 2009
prev sibling next sibling parent Max Samukha <spambox d-coding.com> writes:
On Wed, 11 Nov 2009 10:30:24 -0600, Andrei Alexandrescu
<SeeWebsiteForEmail erdani.org> wrote:

Then different isXxxRange are used by higher-order ranges in defining 
refined interfaces depending on the interfaces offered by their inputs. 
I fail to see how that's terrible.
It is not terrible. It just doesn't give any clue about what exactly is wrong with the entity for which interface validation has failed. I tend to put the code that defines the interface in a separate template to be able to find out the exact error. And because neither _traits(compiles) nor is(typeof) can be currently used to test template instantiations, the code goes to a mixed-in string and the whole affair gets messy. This is the result: private enum inputRangeConcept = q{{ R r; // can define a range object if (r.empty) {} // can test for empty r.popFront; // can invoke next auto h = r.front; // can get the front of the range }}; template InputRangeConcept(R) { mixin ("void _()" ~ inputRangeConcept); } template isInputRange(R) { enum isInputRange = is(typeof(mixin(inputRangeConcept))); } So, for example: alias InputRangeConcept!(int) check; will yield test.d(20): Error: no property 'empty' for type 'int' test.d(21): Error: no property 'popFront' for type 'int' test.d(22): Error: no property 'front' for type 'int' which gives exact information about what is wrong with int candidate for input range position (line numbers are incorrect, though).
Nov 11 2009
prev sibling parent Jeremie Pelletier <jeremiep gmail.com> writes:
Andrei Alexandrescu wrote:
 grauzone wrote:
 Don wrote:
 Christopher Wright wrote:
 grauzone wrote:
 You're not testing for types, you're testing if it compiles. Inside 
 the tested block of code, all sorts of things could go wrong. You 
 can't know if is(typeof(...)) really did what you wanted, or if 
 something broke.
You're testing, "is everything inside that OK?". If you want to know WHY it's wrong, you'd better make sure you're testing something simple.
Andrei's range lib uses it more in a way "does this type support this and that range interface?". Example: http://dsource.org/projects/phobos/browser/trunk/phobos/std/range.d#L58
Then different isXxxRange are used by higher-order ranges in defining refined interfaces depending on the interfaces offered by their inputs. I fail to see how that's terrible. I am very happy D has that feature - no other statically-typed language has it, and it can be used to great effect. Look e.g. at Chain: http://dsource.org/projects/phobos/browser/trunk/phobos/std/range.d#L799 There, the uses of static if (is(...)) allow Chain to define as capable an interface as its inputs allow. Andrei
I really like Andrei's range library, I use it all the time when I need to pass slices of generic types around, it really is more convenient than a pair of iterators. The way I see ranges is as a form of interface without being bound to classes; its the only way to make structs and D arrays pass the isXxxRange traits. The prototypes for using ranges then just go from: void dosomething(T)(IForwardRange!T range) {} to void dosomething(Range)(Range range) if(isForwardRange!Range) {} and it means the same thing, but you can't send a string to IForwardRange.
Nov 12 2009
prev sibling parent reply Bill Baxter <wbaxter gmail.com> writes:
On Wed, Nov 11, 2009 at 8:23 AM, grauzone <none example.net> wrote:
 Don wrote:
 Christopher Wright wrote:
 grauzone wrote:
 You're not testing for types, you're testing if it compiles. Inside the
 tested block of code, all sorts of things could go wrong. You can't know if
 is(typeof(...)) really did what you wanted, or if something broke.
You're testing, "is everything inside that OK?". If you want to know WHY it's wrong, you'd better make sure you're testing something simple.
Andrei's range lib uses it more in a way "does this type support this and that range interface?". Example: http://dsource.org/projects/phobos/browser/trunk/phobos/std/range.d#L58
But notice he also has unit tests for it that check some things which are supposed to pass and not pass. So if the is(typeof()) were failing because of a typo, he'd know it. I think the problem with an interface-like specification is that things like if (r.empty) {} are hard to specify other than by asking if the code compiles. The algo doesn't actually require an r.empty that returns bool. It requires an r.empty that can can be used in a conditional. It's actually ok if r.empty returns null on empty and non-null otherwise. "Does this code compile" is actually the right question to ask, IMHO. But I know what you mean. I just don't know if it's possible to do better. Actually it already errors out if you give it structurally invalid code. For instance all these generate errors: static if(is(typeof{ int x if (x) {} })) static if(is(typeof{ int x; iff (x) {} })) static if(is(typeof{ int x; if (x)) {} })) static if(is(typeof{ int x; for (;) {} })) So I think the only things that give you errors are ones where you've typed an identifier wrong, or asked for function call when you meant indexing etc. Given that, I'm not sure how creating interfaces would make anything different. You could still have typos in your interface declaration. I think it ends up being pretty much equivalent to defining a "template supportsInterface(T)". Having a "myType : implements static Interface" syntax is the moral equivalent of "static assert(supportsInterface!(myType))". The only difference is that a static interface syntax might be able to give you better error messages than "assertion failed". Ok, so I guess that's something that would be valuable: We need some way to get the reason for failure from static if (is(typeof(...)). If you had that, then I think you could write a checkInterface!(T) that reports decent error messages. I think I'll start another thread about that. d.announce clearly isn't the right place for this discussion. ---------- Somewhat related -- this topic ties into something I brought up before. I often find I end up writing bits of code twice: static if (is(typeof({ a[x] += c; }))) { a[x] += c; } else { // fallback } It feels like there should be a construct that compiles some code if it can, otherwise do something else. Maybe: static if { a[x] += c; } else { // fallback } --bb
Nov 12 2009
parent "Denis Koroskin" <2korden gmail.com> writes:
On Thu, 12 Nov 2009 16:01:20 +0300, Bill Baxter <wbaxter gmail.com> wrote:

 On Wed, Nov 11, 2009 at 8:23 AM, grauzone <none example.net> wrote:
 Don wrote:
 Christopher Wright wrote:
 grauzone wrote:
 You're not testing for types, you're testing if it compiles. Inside  
 the
 tested block of code, all sorts of things could go wrong. You can't  
 know if
 is(typeof(...)) really did what you wanted, or if something broke.
You're testing, "is everything inside that OK?". If you want to know WHY it's wrong, you'd better make sure you're testing something simple.
Andrei's range lib uses it more in a way "does this type support this and that range interface?". Example: http://dsource.org/projects/phobos/browser/trunk/phobos/std/range.d#L58
But notice he also has unit tests for it that check some things which are supposed to pass and not pass. So if the is(typeof()) were failing because of a typo, he'd know it. I think the problem with an interface-like specification is that things like if (r.empty) {} are hard to specify other than by asking if the code compiles. The algo doesn't actually require an r.empty that returns bool. It requires an r.empty that can can be used in a conditional. It's actually ok if r.empty returns null on empty and non-null otherwise. "Does this code compile" is actually the right question to ask, IMHO. But I know what you mean. I just don't know if it's possible to do better. Actually it already errors out if you give it structurally invalid code. For instance all these generate errors: static if(is(typeof{ int x if (x) {} })) static if(is(typeof{ int x; iff (x) {} })) static if(is(typeof{ int x; if (x)) {} })) static if(is(typeof{ int x; for (;) {} })) So I think the only things that give you errors are ones where you've typed an identifier wrong, or asked for function call when you meant indexing etc. Given that, I'm not sure how creating interfaces would make anything different. You could still have typos in your interface declaration. I think it ends up being pretty much equivalent to defining a "template supportsInterface(T)". Having a "myType : implements static Interface" syntax is the moral equivalent of "static assert(supportsInterface!(myType))". The only difference is that a static interface syntax might be able to give you better error messages than "assertion failed". Ok, so I guess that's something that would be valuable: We need some way to get the reason for failure from static if (is(typeof(...)). If you had that, then I think you could write a checkInterface!(T) that reports decent error messages. I think I'll start another thread about that. d.announce clearly isn't the right place for this discussion. ---------- Somewhat related -- this topic ties into something I brought up before. I often find I end up writing bits of code twice: static if (is(typeof({ a[x] += c; }))) { a[x] += c; } else { // fallback } It feels like there should be a construct that compiles some code if it can, otherwise do something else. Maybe: static if { a[x] += c; } else { // fallback } --bb
string expression = "a[x] += c"; static if (meta.compiles(expression)) { mixin(expression); } else { // fallback } or even like this: expr expression = "a[x] += c"; static if (expression.compiles) { expression(); // or expression.evaluate(); } else { // fallback }
Nov 12 2009
prev sibling parent rmcguire <rjmcguire gmail.com> writes:
Bill Baxter <wbaxter gmail.com> wrote:
 
 On Mon, Nov 9, 2009 at 4:09 PM, Walter Bright
 <newshound1 digitalmars.com> wrote:
 Looks like Bill Baxter is giving a presentation on D Nov. 18!

 http://www.nwcpp.org/
Yep, that's right, and I'd be quite grateful to you smart folks here if you could share your meta-programming favorites with me! If you've got a real-world example of meta-programming in D that you think is particularly handy, then please send it my way I'm looking for small-but-useful things that are easy to explain, and make something easier than it would be otherwise. Things like places where static if can save your butt, or loop unrolling, and passing code snippets to functions like in std.algorithm. Things like a compile-time raytracer or regexp parser (though quite cool!) are not what I'm after. Too involved for a short talk. --bb
I've use the code below to generate wrappers for my hessian serialization implementation. its not all absolutely necessary but is only 130 lines. import std.stdio; import std.typetuple; import std.traits; import std.metastrings; string[] splitFuncs(string str) {     string[] res;     while (str.length > 0) {         while (str.length > 0 && (' ' == str[0] || ',' == str[0])) {             str = str[1..$];         }         int to = 0;         for (; to < str.length && str[to] != ' ' && str[to] != ','; ++to) {}         if (to > 0) {             res ~= str[0..to];             str = str[to..$];         }     }     return res; } string MethodTypeTuple_mixin(alias a)(string[] methods) { string ret = "TypeTuple!("~ "typeof(&C.init."~methods[0]~")"; foreach (method; methods[1..$]) { ret ~= ",typeof(&C.init."~method~")"; } ret ~= ")"; return ret; } // test case class A { int a; this(int a) { this.a = a; } int getInt(string intname) { return a; } void setInt(int i) { a = i; } string getString(string s) { return s ~"1234"; } } string ProxyMethods_mixin(alias C, string methodstr)() { string ret; foreach(i, t; mixin(MethodTypeTuple_mixin!(C)(splitFuncs(methodstr)))) { // output function header ret ~= "\t"~ReturnType!(t).stringof ~" "~ splitFuncs(methodstr)[i]~"("; // output first arg ret ~= ParameterTypeTuple!(t)[0].stringof~" arg"; // output remainder of args foreach (j, t1; ParameterTypeTuple!(t)[1..$]) { ret ~= ","~t1.stringof~" arg"~std.metastrings.ToString!(j); } // output body ret ~= ") {\n"; // output serialization code // send method name ret ~= "\t\twritefln(\"serialize docall id\"); // the method call byte id\n"; ret ~= "\t\t//serialize!(string)(\""~splitFuncs(methodstr)[i]~"\"); /+ the method name +/\n"; // send args ret ~= "\t\t//serialize!("~ ParameterTypeTuple!(t)[0].stringof~") (arg); /+ the first argument +/\n"; foreach (j, t1; ParameterTypeTuple!(t)[1..$]) { ret ~= "\t\t//serialize!("~ t1.stringof ~")(arg"~ToString!(j)~"); / + argument "~ToString!(j)~" +/\n"; } // receive return type static if (!is(ReturnType!(t) == void)) { pragma(msg, "WARNING: this will always result in Range violation due to no real data. THIS IS JUST A DEMO"); pragma(msg, "\t\t need to implement the actual send/receive"); ret ~= "\t\t//return deserialize!("~ ReturnType!(t).stringof ~") (buffer);\n"; // this is just here to make it still compile even though I've commented out the real deserialize return above static if (is(ReturnType!(t) == int)) { ret ~= "\t\treturn 0;\n"; } else { ret ~= "\t\treturn \"\";\n"; } } ret ~= "\t}\n"; } return ret; } string ProxyClass_mixin(alias C, string methodstr)() { string ret = "new class { ubyte[] buffer;\n"; ret ~= ProxyMethods_mixin!(C, methodstr)(); ret ~= "}\n"; pragma(msg, MethodTypeTuple_mixin!(C)(splitFuncs(methodstr))); return ret; } class ProxyClass(alias C, string methodstr) { ubyte[] buffer; this() { } mixin(ProxyMethods_mixin!(C,methodstr)()); } /+ void serialize(T)(T value) { writefln("serialize"); } T deserialize(T)() { writefln("deserialize"); static if (is(T==int)) { return 1; } else return "asdf"; } +/ void main() { pragma(msg, ProxyClass_mixin!(A,cast(string)"getInt setInt")()); writefln(ProxyClass_mixin!(A,cast(string)"getInt setInt")()); auto c = mixin(ProxyClass_mixin!(A,cast(string)"getInt setInt getString") ()); //pragma(msg, typeof(c).stringof); writefln("c.getInt(\"adsf\"): "~ c.getString("asdf")); auto pc = new ProxyClass!(A, cast(string)"getInt setInt getString"); writefln("ProxyClass: "~ pc.getString("asdf")); }
Nov 13 2009
prev sibling next sibling parent Tomas Lindquist Olsen <tomas.l.olsen gmail.com> writes:
On Tue, Nov 10, 2009 at 1:27 AM, Bill Baxter <wbaxter gmail.com> wrote:
 On Mon, Nov 9, 2009 at 4:09 PM, Walter Bright
 <newshound1 digitalmars.com> wrote:
 Looks like Bill Baxter is giving a presentation on D Nov. 18!

 http://www.nwcpp.org/
Yep, that's right, and I'd be quite grateful to you smart folks here if you could share your meta-programming favorites with me! =C2=A0 If you've got a real-world example of meta-programming in D that you think is particularly handy, then please send it my way I'm looking for small-but-useful things that are easy to explain, and make something easier than it would be otherwise. =C2=A0Things like place=
s
 where static if can save your butt, =C2=A0or loop unrolling, =C2=A0and pa=
ssing
 code snippets to functions like in std.algorithm.

 Things like a compile-time raytracer or regexp parser (though quite
 cool!) are not what I'm after. =C2=A0Too involved for a short talk.

 --bb
I think tuples are a good example of something that makes your life easier, lately I've been very fond of this little snippet:

void delegate() Bind(Args...)(void delegate(Args) dg, Args args) { struct Closure { Args arguments; void delegate(Args) callee; void call() { callee(arguments); } } auto c =3D new Closure; // foreach not strictly necessary, but ldc currently chokes on just an assignment... I should fix that.. foreach(i,a;args) c.arguments[i] =3D a; c.callee =3D dg; return &c.call; } class C { void foo(int,float) {} } void main() { auto c =3D new C; auto dg =3D Bind(&c.foo, 1, 2.0f); // register delegate somewhere } <<<<<<<<<<<<<<<<<<<<<<<< Not sure if this gets easier in C++0x , haven't read up on that... Nothing fancy, but it sure has made my life easier. -Tomas
Nov 12 2009
prev sibling next sibling parent Bill Baxter <wbaxter gmail.com> writes:
On Thu, Nov 12, 2009 at 10:46 AM, Tomas Lindquist Olsen
<tomas.l.olsen gmail.com> wrote:
 On Tue, Nov 10, 2009 at 1:27 AM, Bill Baxter <wbaxter gmail.com> wrote:
 On Mon, Nov 9, 2009 at 4:09 PM, Walter Bright
 <newshound1 digitalmars.com> wrote:
 Looks like Bill Baxter is giving a presentation on D Nov. 18!

 http://www.nwcpp.org/
Yep, that's right, and I'd be quite grateful to you smart folks here if you could share your meta-programming favorites with me! =A0 If you've got a real-world example of meta-programming in D that you think is particularly handy, then please send it my way I'm looking for small-but-useful things that are easy to explain, and make something easier than it would be otherwise. =A0Things like places where static if can save your butt, =A0or loop unrolling, =A0and passing code snippets to functions like in std.algorithm. Things like a compile-time raytracer or regexp parser (though quite cool!) are not what I'm after. =A0Too involved for a short talk. --bb
I think tuples are a good example of something that makes your life easier, lately I've been very fond of this little snippet:

void delegate() Bind(Args...)(void delegate(Args) dg, Args args) { =A0 =A0struct Closure =A0 =A0{ =A0 =A0 =A0 =A0Args arguments; =A0 =A0 =A0 =A0void delegate(Args) callee; =A0 =A0 =A0 =A0void call() =A0 =A0 =A0 =A0{ =A0 =A0 =A0 =A0 =A0 =A0callee(arguments); =A0 =A0 =A0 =A0} =A0 =A0} =A0 =A0auto c =3D new Closure; =A0 =A0// foreach not strictly necessary, but ldc currently chokes on just an assignment... I should fix that.. =A0 =A0foreach(i,a;args) =A0 =A0 =A0 =A0c.arguments[i] =3D a; =A0 =A0c.callee =3D dg; =A0 =A0return &c.call; } class C { =A0 =A0void foo(int,float) {} } void main() { =A0 =A0auto c =3D new C; =A0 =A0auto dg =3D Bind(&c.foo, 1, 2.0f); =A0 =A0// register delegate somewhere } <<<<<<<<<<<<<<<<<<<<<<<< Not sure if this gets easier in C++0x , haven't read up on that...
I think it does. C++0x has variadic templates. And some kind of lambdas/closure thing. So probably it can do something similar. Anyway, the meta- aspect of Bind seems kinda weak. Certainly a nice use of variadic templates and closures, though. --bb
Nov 12 2009
prev sibling next sibling parent Tomas Lindquist Olsen <tomas.l.olsen gmail.com> writes:
On Thu, Nov 12, 2009 at 8:24 PM, Bill Baxter <wbaxter gmail.com> wrote:
 On Thu, Nov 12, 2009 at 10:46 AM, Tomas Lindquist Olsen
 <tomas.l.olsen gmail.com> wrote:
 On Tue, Nov 10, 2009 at 1:27 AM, Bill Baxter <wbaxter gmail.com> wrote:
 On Mon, Nov 9, 2009 at 4:09 PM, Walter Bright
 <newshound1 digitalmars.com> wrote:
 Looks like Bill Baxter is giving a presentation on D Nov. 18!

 http://www.nwcpp.org/
Yep, that's right, and I'd be quite grateful to you smart folks here if you could share your meta-programming favorites with me! =C2=A0 If you've got a real-world example of meta-programming in D that you think is particularly handy, then please send it my way I'm looking for small-but-useful things that are easy to explain, and make something easier than it would be otherwise. =C2=A0Things like pla=
ces
 where static if can save your butt, =C2=A0or loop unrolling, =C2=A0and =
passing
 code snippets to functions like in std.algorithm.

 Things like a compile-time raytracer or regexp parser (though quite
 cool!) are not what I'm after. =C2=A0Too involved for a short talk.

 --bb
I think tuples are a good example of something that makes your life easier, lately I've been very fond of this little snippet:

void delegate() Bind(Args...)(void delegate(Args) dg, Args args) { =C2=A0 =C2=A0struct Closure =C2=A0 =C2=A0{ =C2=A0 =C2=A0 =C2=A0 =C2=A0Args arguments; =C2=A0 =C2=A0 =C2=A0 =C2=A0void delegate(Args) callee; =C2=A0 =C2=A0 =C2=A0 =C2=A0void call() =C2=A0 =C2=A0 =C2=A0 =C2=A0{ =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0callee(arguments); =C2=A0 =C2=A0 =C2=A0 =C2=A0} =C2=A0 =C2=A0} =C2=A0 =C2=A0auto c =3D new Closure; =C2=A0 =C2=A0// foreach not strictly necessary, but ldc currently chokes=
on
 just an assignment... I should fix that..
 =C2=A0 =C2=A0foreach(i,a;args)
 =C2=A0 =C2=A0 =C2=A0 =C2=A0c.arguments[i] =3D a;
 =C2=A0 =C2=A0c.callee =3D dg;

 =C2=A0 =C2=A0return &c.call;
 }

 class C
 {
 =C2=A0 =C2=A0void foo(int,float) {}
 }

 void main()
 {
 =C2=A0 =C2=A0auto c =3D new C;
 =C2=A0 =C2=A0auto dg =3D Bind(&c.foo, 1, 2.0f);
 =C2=A0 =C2=A0// register delegate somewhere
 }

 <<<<<<<<<<<<<<<<<<<<<<<<

 Not sure if this gets easier in C++0x , haven't read up on that...
I think it does. =C2=A0C++0x has variadic templates. =C2=A0And some kind =
of
 lambdas/closure thing. =C2=A0So probably it can do something similar.
 Anyway, the meta- aspect of Bind seems kinda weak. =C2=A0Certainly a nice
 use of variadic templates and closures, though.

 --bb
Just read the Wikipedia entries on Metaprogramming and Template_metaprogramming, I guess I wasn't really aware of the difference. Seems a lot harder to come up with small real-world snippets of the former.
Nov 13 2009
prev sibling next sibling parent Bill Baxter <wbaxter gmail.com> writes:
On Fri, Nov 13, 2009 at 11:38 AM, Tomas Lindquist Olsen
<tomas.l.olsen gmail.com> wrote:
 On Thu, Nov 12, 2009 at 8:24 PM, Bill Baxter <wbaxter gmail.com> wrote:
 On Thu, Nov 12, 2009 at 10:46 AM, Tomas Lindquist Olsen
 <tomas.l.olsen gmail.com> wrote:
 On Tue, Nov 10, 2009 at 1:27 AM, Bill Baxter <wbaxter gmail.com> wrote:
 On Mon, Nov 9, 2009 at 4:09 PM, Walter Bright
 <newshound1 digitalmars.com> wrote:
 Looks like Bill Baxter is giving a presentation on D Nov. 18!

 http://www.nwcpp.org/
Yep, that's right, and I'd be quite grateful to you smart folks here if you could share your meta-programming favorites with me! =A0 If you've got a real-world example of meta-programming in D that you think is particularly handy, then please send it my way I'm looking for small-but-useful things that are easy to explain, and make something easier than it would be otherwise. =A0Things like place=
s
 where static if can save your butt, =A0or loop unrolling, =A0and passi=
ng
 code snippets to functions like in std.algorithm.

 Things like a compile-time raytracer or regexp parser (though quite
 cool!) are not what I'm after. =A0Too involved for a short talk.

 --bb
I think tuples are a good example of something that makes your life easier, lately I've been very fond of this little snippet:

void delegate() Bind(Args...)(void delegate(Args) dg, Args args) { =A0 =A0struct Closure =A0 =A0{ =A0 =A0 =A0 =A0Args arguments; =A0 =A0 =A0 =A0void delegate(Args) callee; =A0 =A0 =A0 =A0void call() =A0 =A0 =A0 =A0{ =A0 =A0 =A0 =A0 =A0 =A0callee(arguments); =A0 =A0 =A0 =A0} =A0 =A0} =A0 =A0auto c =3D new Closure; =A0 =A0// foreach not strictly necessary, but ldc currently chokes on just an assignment... I should fix that.. =A0 =A0foreach(i,a;args) =A0 =A0 =A0 =A0c.arguments[i] =3D a; =A0 =A0c.callee =3D dg; =A0 =A0return &c.call; } class C { =A0 =A0void foo(int,float) {} } void main() { =A0 =A0auto c =3D new C; =A0 =A0auto dg =3D Bind(&c.foo, 1, 2.0f); =A0 =A0// register delegate somewhere } <<<<<<<<<<<<<<<<<<<<<<<< Not sure if this gets easier in C++0x , haven't read up on that...
I think it does. =A0C++0x has variadic templates. =A0And some kind of lambdas/closure thing. =A0So probably it can do something similar. Anyway, the meta- aspect of Bind seems kinda weak. =A0Certainly a nice use of variadic templates and closures, though. --bb
Just read the Wikipedia entries on Metaprogramming and Template_metaprogramming, I guess I wasn't really aware of the difference. Seems a lot harder to come up with small real-world snippets of the forme=
r. The way I read it, template metaprogramming is a kind of metaprogramming. Metaprogramming using templates. And ctfe/string-mixin metaprogramming are another, macro metaprogramming another etc. I think the phrase "template metaprogramming" just took particularly strong hold because of C++ where templates are always required for accomplishing pretty much any kind of metaprogramming. --bb
Nov 13 2009
prev sibling next sibling parent reply Walter Bright <newshound1 digitalmars.com> writes:
Walter Bright wrote:
 Looks like Bill Baxter is giving a presentation on D Nov. 18!
 http://www.nwcpp.org/
And Bill did a great job!
Nov 19 2009
parent Long Chang <changedalone gmail.com> writes:
nice work
Nov 22 2009
prev sibling parent reply Lutger <lutger.blijdestijn gmail.com> writes:
Walter Bright wrote:

 Looks like Bill Baxter is giving a presentation on D Nov. 18!
 
 http://www.nwcpp.org/
slides are there! Very pretty, I bet it was a fine presentation. The slides are informative, good examples.
Nov 24 2009
next sibling parent Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> writes:
Lutger wrote:
 Walter Bright wrote:
 
 Looks like Bill Baxter is giving a presentation on D Nov. 18!

 http://www.nwcpp.org/
slides are there! Very pretty, I bet it was a fine presentation. The slides are informative, good examples.
Seconded. Very well done Bill. Andrei
Nov 24 2009
prev sibling next sibling parent reply Bill Baxter <wbaxter gmail.com> writes:
On Tue, Nov 24, 2009 at 3:15 PM, Lutger <lutger.blijdestijn gmail.com> wrote:
 Walter Bright wrote:

 Looks like Bill Baxter is giving a presentation on D Nov. 18!

 http://www.nwcpp.org/
slides are there! Very pretty, I bet it was a fine presentation. The slides are informative, good examples.
Thanks Walter, Long, Lutger & Andrei! They took a video too, so there should be video up soon. I didn't realize it, but Walter gave a talk called "Metaprogramming in D" for the NWCPP back in January. Doh! They must be thinking "what's with all these D metaprogramming talks?!" --bb
Nov 24 2009
parent reply "Nick Sabalausky" <a a.a> writes:
"Bill Baxter" <wbaxter gmail.com> wrote in message 
news:mailman.513.1259106953.20261.digitalmars-d-announce puremagic.com...
 On Tue, Nov 24, 2009 at 3:15 PM, Lutger <lutger.blijdestijn gmail.com> 
 wrote:
 Walter Bright wrote:

 Looks like Bill Baxter is giving a presentation on D Nov. 18!

 http://www.nwcpp.org/
slides are there! Very pretty, I bet it was a fine presentation. The slides are informative, good examples.
Thanks Walter, Long, Lutger & Andrei! They took a video too, so there should be video up soon. I didn't realize it, but Walter gave a talk called "Metaprogramming in D" for the NWCPP back in January. Doh! They must be thinking "what's with all these D metaprogramming talks?!" --bb
Hey, I recognize some of those examples :) Looking forward to the video.
Nov 24 2009
parent Bill Baxter <wbaxter gmail.com> writes:
On Tue, Nov 24, 2009 at 4:55 PM, Nick Sabalausky <a a.a> wrote:
 "Bill Baxter" <wbaxter gmail.com> wrote in message
 news:mailman.513.1259106953.20261.digitalmars-d-announce puremagic.com...
 On Tue, Nov 24, 2009 at 3:15 PM, Lutger <lutger.blijdestijn gmail.com>
 wrote:
 Walter Bright wrote:

 Looks like Bill Baxter is giving a presentation on D Nov. 18!

 http://www.nwcpp.org/
slides are there! Very pretty, I bet it was a fine presentation. The slides are informative, good examples.
Thanks Walter, Long, Lutger & Andrei! They took a video too, so there should be video up soon. I didn't realize it, but Walter gave a talk called "Metaprogramming in D" for the NWCPP back in January. =A0Doh! =A0They must be thinking "what=
's
 with all these D metaprogramming talks?!"

 --bb
Hey, I recognize some of those examples :) =A0Looking forward to the vide=
o. Yep, thanks for the ideas & discussion. --bb
Nov 24 2009
prev sibling parent reply BCS <none anon.com> writes:
Hello Lutger,

 Walter Bright wrote:
 
 Looks like Bill Baxter is giving a presentation on D Nov. 18!
 
 http://www.nwcpp.org/
 
slides are there! Very pretty, I bet it was a fine presentation. The slides are informative, good examples.
re: the slides, are they avalable in .ppt or pdf for us ludites?
Nov 24 2009
parent reply "Nick Sabalausky" <a a.a> writes:
"BCS" <none anon.com> wrote in message 
news:a6268ffd6138cc3b42e6f50076 news.digitalmars.com...
 Hello Lutger,

 Walter Bright wrote:

 Looks like Bill Baxter is giving a presentation on D Nov. 18!

 http://www.nwcpp.org/
slides are there! Very pretty, I bet it was a fine presentation. The slides are informative, good examples.
re: the slides, are they avalable in .ppt or pdf for us ludites?
http://www.semitwist.com/download/NWCPP-D-meta-baxter-11-18-2009.ppt http://www.semitwist.com/download/NWCPP-D-meta-baxter-11-18-2009.odp OpenOffice 3 can open the original .pptx, but the font sizes are all messed up. The above ones should work fine though.
Nov 24 2009
parent BCS <none anon.com> writes:
Hello Nick,

 re: the slides, are they avalable in .ppt or pdf for us ludites?
 
http://www.semitwist.com/download/NWCPP-D-meta-baxter-11-18-2009.ppt http://www.semitwist.com/download/NWCPP-D-meta-baxter-11-18-2009.odp OpenOffice 3 can open the original .pptx, but the font sizes are all messed up. The above ones should work fine though.
thanks
Nov 24 2009