digitalmars.D.announce - Metaprogramming in D : Some Real-world Examples
- Walter Bright (2/2) Nov 09 2009 Looks like Bill Baxter is giving a presentation on D Nov. 18!
- Bill Baxter (13/15) Nov 09 2009 Yep, that's right, and I'd be quite grateful to you smart folks here
- Andrei Alexandrescu (4/24) Nov 09 2009 std.random has code that checks the parameters of a congruential RNG
- Bill Baxter (8/33) Nov 12 2009 ng
- Andrei Alexandrescu (4/35) Nov 12 2009 It's been online for a while.
- Bill Baxter (6/47) Nov 12 2009 s
- Nick Sabalausky (210/226) Nov 09 2009 I have a few things, mostly part of my SemiTwist D Tools project
- Bill Baxter (57/269) Nov 12 2009 Hi Nick,
- Nick Sabalausky (14/31) Nov 12 2009 Heh, I tend to forget about that one. That's from the "semitwist.util.te...
- Nick Sabalausky (12/27) Nov 12 2009 One other idea I had for expanding on that NewStyle_StaticToken would be...
- Denis Koroskin (47/63) Nov 10 2009 kprintf (a printf variant) in XoMB is a nice example imo. It accepts
- Bill Baxter (6/10) Nov 12 2009 Nice. 400 lines is a little long for this purpose, though. Maybe a
- Lutger (62/82) Nov 10 2009 Great, I hope to see some slides or a video!
- Bill Baxter (19/99) Nov 12 2009 n
- Lutger (8/28) Nov 12 2009 Interesting. I noticed it's also possible to pass a module as an alias a...
- Jacob Carlborg (13/29) Nov 10 2009 This is invaluable to me, which makes it possible to do some form of
- Lars T. Kyllingstad (8/36) Nov 10 2009 There are forces at work (Don, that is) attempting to get rid of that
- Jacob Carlborg (3/39) Nov 10 2009 Yes, it's very ugly. As long as the functionality is left in the
- Bill Baxter (15/53) Nov 10 2009 g
- grauzone (2/42) Nov 10 2009
- Andrei Alexandrescu (4/47) Nov 10 2009 I think testing types during compilation isn't bad. Under what
- grauzone (20/68) Nov 11 2009 You're not testing for types, you're testing if it compiles. Inside the
- Christopher Wright (3/6) Nov 11 2009 So it requires caution, and you want to keep the contents small. It's
- Don (8/15) Nov 11 2009 You're testing, "is everything inside that OK?". If you want to know WHY...
- grauzone (7/24) Nov 11 2009 Andrei's range lib uses it more in a way "does this type support this
- Andrei Alexandrescu (10/24) Nov 11 2009 Then different isXxxRange are used by higher-order ranges in defining
- grauzone (26/55) Nov 11 2009 That means if one isXxxRange fails because the user maybe made a typo in...
- Jacob Carlborg (4/59) Nov 12 2009 The check doesn't have to look like that. The check can be inside the
- Max Samukha (31/34) Nov 11 2009 It is not terrible. It just doesn't give any clue about what exactly
- Jeremie Pelletier (12/41) Nov 12 2009 I really like Andrei's range library, I use it all the time when I need
- Bill Baxter (52/67) Nov 12 2009 But notice he also has unit tests for it that check some things which
- Denis Koroskin (14/87) Nov 12 2009 string expression = "a[x] += c";
- rmcguire (130/151) Nov 13 2009 I've use the code below to generate wrappers for my hessian serializatio...
- Tomas Lindquist Olsen (38/55) Nov 12 2009 ssing
- Bill Baxter (7/63) Nov 12 2009 I think it does. C++0x has variadic templates. And some kind of
- Tomas Lindquist Olsen (9/82) Nov 13 2009 passing
- Bill Baxter (13/94) Nov 13 2009 s
- Walter Bright (2/4) Nov 19 2009 And Bill did a great job!
- Long Chang (1/1) Nov 22 2009 nice work
- Lutger (3/6) Nov 24 2009 slides are there! Very pretty, I bet it was a fine presentation. The sli...
- Andrei Alexandrescu (3/11) Nov 24 2009 Seconded. Very well done Bill.
- Bill Baxter (7/13) Nov 24 2009 Thanks Walter, Long, Lutger & Andrei!
- Nick Sabalausky (3/21) Nov 24 2009 Hey, I recognize some of those examples :) Looking forward to the video...
- Bill Baxter (5/30) Nov 24 2009 o.
- BCS (2/11) Nov 24 2009 re: the slides, are they avalable in .ppt or pdf for us ludites?
- Nick Sabalausky (6/17) Nov 24 2009 http://www.semitwist.com/download/NWCPP-D-meta-baxter-11-18-2009.ppt
- BCS (2/11) Nov 24 2009 thanks
Looks like Bill Baxter is giving a presentation on D Nov. 18! http://www.nwcpp.org/
Nov 09 2009
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
Bill Baxter wrote:On Mon, Nov 9, 2009 at 4:09 PM, Walter Bright <newshound1 digitalmars.com> wrote:std.random has code that checks the parameters of a congruential RNG during compilation. That's also an example in TDPL. AndreiLooks 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
On Mon, Nov 9, 2009 at 6:03 PM, Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> wrote:Bill Baxter wrote:ngOn Mon, Nov 9, 2009 at 4:09 PM, Walter Bright <newshound1 digitalmars.com> wrote:std.random has code that checks the parameters of a congruential RNG duri=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. --bbcompilation. 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
Bill Baxter wrote:On Mon, Nov 9, 2009 at 6:03 PM, Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> wrote:It's been online for a while. http://erdani.com/tdpl/excerpt.pdf AndreiBill Baxter wrote: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"? --bbOn Mon, Nov 9, 2009 at 4:09 PM, Walter Bright <newshound1 digitalmars.com> wrote:std.random has code that checks the parameters of a congruential RNG during compilation. That's also an example in TDPL.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 12 2009
On Thu, Nov 12, 2009 at 7:53 AM, Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> wrote:Bill Baxter wrote:sOn 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=ngwhere static if can save your butt, =A0or loop unrolling, =A0and passi=Thanks, I guess I saw that at some point, but forgot what it contained. --bbIt's been online for a while. http://erdani.com/tdpl/excerpt.pdfThis looks good. Any chance you could send me the snippet of the book that explains the rationale for what constitutes "proper linear congruential parameters"? --bbcode 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. --bbstd.random has code that checks the parameters of a congruential RNG during compilation. That's also an example in TDPL.
Nov 12 2009
"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/): === 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 } -------------------------------------------------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
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.dQuick 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.dQuick 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=ealDRY 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.dQuick 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=adof 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=uchof the usefulness of JUnit-style libs, but without the bulk of wrapping things like '=3D=3D' and '||' in classes/structs or forcing unnatural syn=taxlike '(a.equals(b)).or(c.notEquals(d))'. Also reports unexpected exceptio=nsand 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.dSimple Test App: http://www.dsource.org/projects/semitwist/browser/trunk/src/semitwist/app=s/tests/deferAssertTest/main.dQuick 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=efoo 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=3DAnother 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 =(infact, *must* already know) the token names, so the flexibility doesn't he=lpthem 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'=sextra 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=asalready taken by another token?). Also, the new static class definition would probably need to be duplicated for each token. But all those proble=mscan be solved in D quite easily with just a very small amount of some ver=ysimple 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
"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).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.[various]This is another one that C++ people would just throw macros at and wonder what the big deal is.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.=== 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.Thanks for writing all these up.No prob! :)
Nov 12 2009
"Nick Sabalausky" <a a.a> wrote in message news:hdgt9q$vti$1 digitalmars.com...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."Bill Baxter" <wbaxter gmail.com> wrote in message news:mailman.337.1258023453.20261.digitalmars-d-announce puremagic.com... Hi Nick,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.=== 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.
Nov 12 2009
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: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! * */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 10 2009
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.dNice. 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
Bill Baxter wrote:On Mon, Nov 9, 2009 at 4:09 PM, Walter Bright <newshound1 digitalmars.com> wrote: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); }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 10 2009
On Tue, Nov 10, 2009 at 3:32 AM, Lutger <lutger.blijdestijn gmail.com> wrot= e:Bill Baxter wrote:nOn Mon, Nov 9, 2009 at 4:09 PM, Walter Bright <newshound1 digitalmars.com> wrote: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=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. --bbyou 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
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). --bbswizzling 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
On 11/10/09 01:27, Bill Baxter wrote:On Mon, Nov 9, 2009 at 4:09 PM, Walter Bright <newshound1 digitalmars.com> wrote: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) methodLooks 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 10 2009
Jacob Carlborg wrote:On 11/10/09 01:27, Bill Baxter wrote: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. -LarsOn Mon, Nov 9, 2009 at 4:09 PM, Walter Bright <newshound1 digitalmars.com> wrote: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 */ })))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 10 2009
On 11/10/09 13:29, Lars T. Kyllingstad wrote:Jacob Carlborg wrote: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.On 11/10/09 01:27, Bill Baxter wrote: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. -LarsOn Mon, Nov 9, 2009 at 4:09 PM, Walter Bright <newshound1 digitalmars.com> wrote: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 */ })))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 10 2009
On Tue, Nov 10, 2009 at 4:29 AM, Lars T. Kyllingstad <public kyllingen.nospamnet> wrote:Jacob Carlborg wrote:gOn 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=kcode 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. --bbThis is invaluable to me, which makes it possible to do some form of duc=ytyping 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=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.htmlIn my humble opinion, is(typeof({...})) is an ugly creature. I really don='tthink 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
Lars T. Kyllingstad wrote:Jacob Carlborg wrote:Who cares about "ugly" syntax, if the idea is bad in the first place?On 11/10/09 01:27, Bill Baxter wrote: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.On Mon, Nov 9, 2009 at 4:09 PM, Walter Bright <newshound1 digitalmars.com> wrote: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 */ })))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-Lars
Nov 10 2009
grauzone wrote:Lars T. Kyllingstad wrote:I think testing types during compilation isn't bad. Under what circumstances is it? AndreiJacob Carlborg wrote:Who cares about "ugly" syntax, if the idea is bad in the first place?On 11/10/09 01:27, Bill Baxter wrote: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.On Mon, Nov 9, 2009 at 4:09 PM, Walter Bright <newshound1 digitalmars.com> wrote: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 */ })))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 10 2009
Andrei Alexandrescu 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. 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.Lars T. Kyllingstad wrote:I think testing types during compilation isn't bad. Under what circumstances is it?Jacob Carlborg wrote:Who cares about "ugly" syntax, if the idea is bad in the first place?On 11/10/09 01:27, Bill Baxter wrote: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.On Mon, Nov 9, 2009 at 4:09 PM, Walter Bright <newshound1 digitalmars.com> wrote: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 */ })))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. --bbAndrei
Nov 11 2009
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
Christopher Wright wrote:grauzone wrote: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.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.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
Don wrote:Christopher Wright wrote: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#L58grauzone wrote: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.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.And if it doesn't pass, you know something is not ok? Then shouldn't you raise an error? Oh wait...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.True; that's another use of this feature.
Nov 11 2009
grauzone wrote:Don 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. 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. AndreiChristopher Wright wrote: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#L58grauzone wrote: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.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.
Nov 11 2009
Andrei Alexandrescu wrote:grauzone wrote: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.Don wrote:Then different isXxxRange are used by higher-order ranges in defining refined interfaces depending on the interfaces offered by their inputs.Christopher Wright wrote: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#L58grauzone wrote: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.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.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
On 11/11/09 17:58, grauzone wrote:Andrei Alexandrescu wrote: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.grauzone wrote: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.Don wrote:Then different isXxxRange are used by higher-order ranges in defining refined interfaces depending on the interfaces offered by their inputs.Christopher Wright wrote: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#L58grauzone wrote: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.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.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
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
Andrei Alexandrescu wrote:grauzone wrote: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.Don 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. 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. AndreiChristopher Wright wrote: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#L58grauzone wrote: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.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.
Nov 12 2009
On Wed, Nov 11, 2009 at 8:23 AM, grauzone <none example.net> wrote:Don wrote: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 } --bbChristopher Wright wrote: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#L58grauzone wrote: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.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.
Nov 12 2009
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: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 }Don wrote: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 } --bbChristopher Wright wrote: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#L58grauzone wrote: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.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.
Nov 12 2009
Bill Baxter <wbaxter gmail.com> wrote:On Mon, Nov 9, 2009 at 4:09 PM, Walter Bright <newshound1 digitalmars.com> wrote: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")); }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 13 2009
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:sLooks 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=where static if can save your butt, =C2=A0or loop unrolling, =C2=A0and pa=ssingcode 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. --bbI 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
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: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. --bbOn Mon, Nov 9, 2009 at 4:09 PM, Walter Bright <newshound1 digitalmars.com> wrote:I think tuples are a good example of something that makes your life easier, lately I've been very fond of this little snippet: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. --bbvoid 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...
Nov 12 2009
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:cesOn 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=passingwhere static if can save your butt, =C2=A0or loop unrolling, =C2=A0and =oncode 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. --bbI 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=ofjust 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 =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. --bbJust 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
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:sOn 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=ngwhere static if can save your butt, =A0or loop unrolling, =A0and passi=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. --bbJust 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=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. --bbcode 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. --bbI 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...
Nov 13 2009
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
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
Lutger wrote:Walter Bright wrote:Seconded. Very well done Bill. AndreiLooks 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
On Tue, Nov 24, 2009 at 3:15 PM, Lutger <lutger.blijdestijn gmail.com> wrote:Walter Bright wrote: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?!" --bbLooks 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
"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:Hey, I recognize some of those examples :) Looking forward to the video.Walter Bright wrote: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?!" --bbLooks 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
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...'sOn Tue, Nov 24, 2009 at 3:15 PM, Lutger <lutger.blijdestijn gmail.com> wrote:Walter Bright wrote: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=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.o. Yep, thanks for the ideas & discussion. --bbwith all these D metaprogramming talks?!" --bbHey, I recognize some of those examples :) =A0Looking forward to the vide=
Nov 24 2009
Hello Lutger,Walter Bright wrote:re: the slides, are they avalable in .ppt or pdf for us ludites?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
"BCS" <none anon.com> wrote in message news:a6268ffd6138cc3b42e6f50076 news.digitalmars.com...Hello Lutger,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.Walter Bright wrote:re: the slides, are they avalable in .ppt or pdf for us ludites?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
Hello Nick,thanksre: 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