www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.announce - My first email to Walter, ever

reply Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> writes:
While doing some unrelated research I stumbled upon my very first email 
to Walter, dated April 26, 2004. I liked to see from today's perspective 
where a great collaboration and friendship have started. I thought 
others would also enjoy to see it, so I'm sharing it with Walter's 
approval and a few minor edits.

On 4/26/04 6:54 PM, Andrei Alexandrescu wrote:
 [Walter: I'm going to be ruthless. Put your bulletproof vest on.]

 Hi Walter, this is Andrei, we met at SD in Santa Clara.

 I was bitching to myself and then together with a friend (e-meet
 [...]) about how hard it is to do metaprogramming in C++. He
 mentioned D is much better at it, and we browsed the online
 documentation for D's templates
 (http://www.digitalmars.com/d/template.html), which we noticed
 (apologies if I am wrong) is not much more more than a
 cleaned-syntax version of C++'s templates, which in turn are
  [...].

 That sucks.

 So I said I'd give you the highest order bits of what I think what a
 better language for metaprogramming ought to be like. In spite of my
 ruthlessness, please accept this as a statement of hope that you'd
 be willing to think about this and do something about it.

 A metalanguage should bear the same programming style as the base
 language that it serves. I think that's only fair: the programmer
 learns one syntax and set of semantics (e.g. conditionals,
 iterations, objects...), and applies it as transparently as it gets
 to both metaprogramming and regular programming. C++ has a rich
 mixed-mode language for straight programming, and a half-assed (or
 should I say quarter-assed) functional language for metaprogramming.
 You carried this schism in D, while just cleaning the corners.

 Terrible. If you have conditionals, iteration, functions, and objects
 in D's straight programming support, you should have conditionals,
 iteration, functions, and objects in D's metalanguage. (I'm not
 asking for things like virtuals, exceptions, contracts, and other
 higher-order stuff on grounds that metaprograms are usually smaller
 and aren't subjected to as many scale issues as regular programs
 are.) Those should be combined with introspection primitives, such
 as:

 * The venerable typeof

 * For a class, enumerate all of its members, and figure out their
 attributes (protection level, static or not, type...)

 * For a module/namespace, enumerate all of its symbols and figure
 out their attributes.

 * For a function, figure out its return type and the type of each of
 its formal arguments.

 * Figure out if a certain function exists (that should be easy if
 you have the tools above). That will be useful to decide, for
 example, if an iterator supports random access.

 * And if you really want to go meta, define metacode that can take
 an AST node as a parameter and can visit the AST and figure out what
 each node is. That would allow things such as loop fusion and other
 advanced stuff. But for now, let's leave those aside.

 Does anything make sense so far? :o)



 Andrei
Jul 06 2013
next sibling parent reply Andrej Mitrovic <andrej.mitrovich gmail.com> writes:
On 7/7/13, Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> wrote:
 While doing some unrelated research I stumbled upon my very first email
 to Walter, dated April 26, 2004.
That's a cool teaser, but how did the discussion continue? :)
Jul 07 2013
parent reply Walter Bright <newshound2 digitalmars.com> writes:
On 7/7/2013 5:09 AM, Andrej Mitrovic wrote:
 On 7/7/13, Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> wrote:
 While doing some unrelated research I stumbled upon my very first email
 to Walter, dated April 26, 2004.
That's a cool teaser, but how did the discussion continue? :)
Generally along these lines: "And you, Scarecrow, have the effrontery to ask for a brain, you billowing bale of bovine fodder!"
Jul 07 2013
parent "Joseph Rushton Wakeling" <joseph.wakeling webdrake.net> writes:
On Sunday, 7 July 2013 at 22:03:17 UTC, Walter Bright wrote:
 On 7/7/2013 5:09 AM, Andrej Mitrovic wrote:
 That's a cool teaser, but how did the discussion continue? :)
Generally along these lines: "And you, Scarecrow, have the effrontery to ask for a brain, you billowing bale of bovine fodder!"
What happened when Toto pulled back the curtain? :-)
Jul 08 2013
prev sibling next sibling parent Marco Leise <Marco.Leise gmx.de> writes:
Am Sat, 06 Jul 2013 20:02:16 -0700
schrieb Andrei Alexandrescu <SeeWebsiteForEmail erdani.org>:

 * The venerable typeof
check
 * For a class, enumerate all of its members, and figure out their
 attributes (protection level, static or not, type...)
check
 * For a module/namespace, enumerate all of its symbols and figure
 out their attributes.
check
 * For a function, figure out its return type and the type of each of
 its formal arguments.
check
 * Figure out if a certain function exists (that should be easy if
 you have the tools above). That will be useful to decide, for
 example, if an iterator supports random access.
check
 * And if you really want to go meta, define metacode that can take
 an AST node as a parameter and can visit the AST and figure out what
 each node is. That would allow things such as loop fusion and other
 advanced stuff. But for now, let's leave those aside.
che... oh _that_ topic. I think you have done some really good team work there. And I may add Walter's good intuition to make the front end reusable for GDC and LDC. Btw, you didn't want to start a new discussion about AST manipulation through the back door, did you? ;) -- Marco
Jul 07 2013
prev sibling next sibling parent reply "Peter Alexander" <peter.alexander.au gmail.com> writes:
On Sunday, 7 July 2013 at 03:03:03 UTC, Andrei Alexandrescu wrote:
 Terrible. If you have conditionals, iteration, functions, and 
 objects
 in D's straight programming support, you should have 
 conditionals,
 iteration, functions, and objects in D's metalanguage.
:-( template allSatisfy(alias F, T...) { static if (T.length == 0) { enum allSatisfy = true; } else static if (T.length == 1) { enum allSatisfy = F!(T[0]); } else { enum allSatisfy = allSatisfy!(F, T[ 0 .. $/2]) && allSatisfy!(F, T[$/2 .. $ ]); } } Still looks like half-assed functional programming to me. Where's the iteration? Why can't I write this? template allSatisfy(alias F, T...) { foreach(t; T) if (!F!(t)) return false; return true; } (Those are rhetorical questions btw, before anyone links me to a D tutorial). We're almost there with CTFE, but CTFE can only run functions that could run at runtime. In a crazy world where types were first class objects, stuff like this would be feasible. Or perhaps we just need a compile-time metalanguage that allows things like this to be run with CTFE?
Jul 07 2013
next sibling parent "John Colvin" <john.loughran.colvin gmail.com> writes:
On Sunday, 7 July 2013 at 12:27:02 UTC, Peter Alexander wrote:
 On Sunday, 7 July 2013 at 03:03:03 UTC, Andrei Alexandrescu 
 wrote:
 Terrible. If you have conditionals, iteration, functions, and 
 objects
 in D's straight programming support, you should have 
 conditionals,
 iteration, functions, and objects in D's metalanguage.
:-( template allSatisfy(alias F, T...) { static if (T.length == 0) { enum allSatisfy = true; } else static if (T.length == 1) { enum allSatisfy = F!(T[0]); } else { enum allSatisfy = allSatisfy!(F, T[ 0 .. $/2]) && allSatisfy!(F, T[$/2 .. $ ]); } } Still looks like half-assed functional programming to me. Where's the iteration? Why can't I write this? template allSatisfy(alias F, T...) { foreach(t; T) if (!F!(t)) return false; return true; } (Those are rhetorical questions btw, before anyone links me to a D tutorial). We're almost there with CTFE, but CTFE can only run functions that could run at runtime. In a crazy world where types were first class objects, stuff like this would be feasible. Or perhaps we just need a compile-time metalanguage that allows things like this to be run with CTFE?
So what you're effectively asking for is for templates to be compile-time functions where types are first class variables. I would love that.
Jul 07 2013
prev sibling next sibling parent reply Timon Gehr <timon.gehr gmx.ch> writes:
On 07/07/2013 02:27 PM, Peter Alexander wrote:
 ...

 We're almost there with CTFE, but CTFE can only run functions that could
 run at runtime. In a crazy world where types were first class objects,
 stuff like this would be feasible. Or perhaps we just need a
 compile-time metalanguage that allows things like this to be run with CTFE?
Almost there indeed. http://d.puremagic.com/issues/show_bug.cgi?id=9945
Jul 07 2013
parent "Peter Alexander" <peter.alexander.au gmail.com> writes:
On Sunday, 7 July 2013 at 13:20:14 UTC, Timon Gehr wrote:
 On 07/07/2013 02:27 PM, Peter Alexander wrote:
 ...

 We're almost there with CTFE, but CTFE can only run functions 
 that could
 run at runtime. In a crazy world where types were first class 
 objects,
 stuff like this would be feasible. Or perhaps we just need a
 compile-time metalanguage that allows things like this to be 
 run with CTFE?
Almost there indeed. http://d.puremagic.com/issues/show_bug.cgi?id=9945
Hmmm.... I was thinking about encoding/decoding types, but it doesn't help with template instantiations. You still need a separate compile time language. bool allSatisfy(alias F)(TypeInfo[] typeIds) { foreach(t; typeIds) if (!F!(__traits(typeFromId, t))) <---- How do you do this step? return false; return true; } Or am I missing something?
Jul 07 2013
prev sibling next sibling parent reply Artur Skawina <art.08.09 gmail.com> writes:
On 07/07/13 14:27, Peter Alexander wrote:
 template allSatisfy(alias F, T...)
 {
     static if (T.length == 0)
     {
         enum allSatisfy = true;
     }
     else static if (T.length == 1)
     {
         enum allSatisfy = F!(T[0]);
     }
     else
     {
         enum allSatisfy =
             allSatisfy!(F, T[ 0  .. $/2]) &&
             allSatisfy!(F, T[$/2 ..  $ ]);
     }
 }
 
 Still looks like half-assed functional programming to me.
 
 Where's the iteration? Why can't I write this?
 
 template allSatisfy(alias F, T...) {
     foreach(t; T)
         if (!F!(t))
             return false;
     return true;
 }
 
 (Those are rhetorical questions btw, before anyone links me to a D tutorial).
template allSatisfy(alias F, T...) { enum allSatisfy = { foreach (E; T) if (!F!E) return false; return true; }(); } // And no, it isn't perfect. But not /that/ much is missing. // It's the more complex cases that would benefit from more meta features. artur
Jul 07 2013
parent Nick Sabalausky <SeeWebsiteToContactMe semitwist.com> writes:
On Sun, 07 Jul 2013 15:23:03 +0200
Artur Skawina <art.08.09 gmail.com> wrote:
 
 template allSatisfy(alias F, T...) {
    enum allSatisfy = {
       foreach (E; T)
          if (!F!E)
             return false;
       return true;
    }();
 }
 
 // And no, it isn't perfect. But not /that/ much is missing.
 // It's the more complex cases that would benefit from more meta
 features.
 
It'd be even nicer when/if this becomes possible (I *think* I remember Walter saying it was planned...): enum allSatisfy(alias F, T...) = { foreach (E; T) if (!F!E) return false; return true; }();
Jul 07 2013
prev sibling next sibling parent Andrej Mitrovic <andrej.mitrovich gmail.com> writes:
On 7/7/13, Peter Alexander <peter.alexander.au gmail.com> wrote:
 Still looks like half-assed functional programming to me.
Yep I agree.
 Where's the iteration? Why can't I write this?

 template allSatisfy(alias F, T...) {
      foreach(t; T)
          if (!F!(t))
              return false;
      return true;
 }
Also why not be able to write this (yes I know we can use Filter!() but this is just an example): template GetIntegrals(Types...) { foreach (T; Types) { static if (isIntegral!T) GetIntegrals ~= T; // GetIntegrals becomes a typetuple } } This beats the whole recursive template madness which we always have to write (again there's the D language, and the "template" language, just like in C++) Maybe it would even speed things up not having to recursively instantiate the template many times.
Jul 07 2013
prev sibling next sibling parent "QAston" <qaston gmail.com> writes:
On Sunday, 7 July 2013 at 12:27:02 UTC, Peter Alexander wrote:
 On Sunday, 7 July 2013 at 03:03:03 UTC, Andrei Alexandrescu 
 wrote:
 Terrible. If you have conditionals, iteration, functions, and 
 objects
 in D's straight programming support, you should have 
 conditionals,
 iteration, functions, and objects in D's metalanguage.
:-( template allSatisfy(alias F, T...) { static if (T.length == 0) { enum allSatisfy = true; } else static if (T.length == 1) { enum allSatisfy = F!(T[0]); } else { enum allSatisfy = allSatisfy!(F, T[ 0 .. $/2]) && allSatisfy!(F, T[$/2 .. $ ]); } } Still looks like half-assed functional programming to me. Where's the iteration? Why can't I write this? template allSatisfy(alias F, T...) { foreach(t; T) if (!F!(t)) return false; return true; } (Those are rhetorical questions btw, before anyone links me to a D tutorial). We're almost there with CTFE, but CTFE can only run functions that could run at runtime. In a crazy world where types were first class objects, stuff like this would be feasible. Or perhaps we just need a compile-time metalanguage that allows things like this to be run with CTFE?
Static foreach would help, at least in my case: http://forum.dlang.org/post/ebvrirxozwllqjbffwzh forum.dlang.org Sadly, there are more important issues (shared libs, 83 PRs in dmd) so this will probably have to wait for better times.
Jul 07 2013
prev sibling parent "Kagamin" <spam here.lot> writes:
On Sunday, 7 July 2013 at 12:27:02 UTC, Peter Alexander wrote:
 :-(

 template allSatisfy(alias F, T...)
 {
     static if (T.length == 0)
     {
         enum allSatisfy = true;
     }
     else static if (T.length == 1)
     {
         enum allSatisfy = F!(T[0]);
     }
     else
     {
         enum allSatisfy =
             allSatisfy!(F, T[ 0  .. $/2]) &&
             allSatisfy!(F, T[$/2 ..  $ ]);
     }
 }
It's deplhi-style http://www.freepascal.org/docs-html/ref/refse77.html#x155-16500014.3
Jul 08 2013
prev sibling next sibling parent "Xinok" <xinok live.com> writes:
On Sunday, 7 July 2013 at 03:03:03 UTC, Andrei Alexandrescu wrote:
 On 4/26/04 6:54 PM, Andrei Alexandrescu wrote:
 I was bitching to myself and then together with a friend 
 (e-meet
 [...]) about how hard it is to do metaprogramming in C++. He
 mentioned D is much better at it, and we browsed the online
 documentation for D's templates
 (http://www.digitalmars.com/d/template.html), which we noticed
 (apologies if I am wrong) is not much more more than a
 cleaned-syntax version of C++'s templates, which in turn are
 [...].
You may hold a different opinion today, and my opinion is worthless this point. But my two cents, I think (1) static-if and (2) making templates independent of classes and functions were both huge steps forward.
Jul 07 2013
prev sibling parent "deadalnix" <deadalnix gmail.com> writes:
On Sunday, 7 July 2013 at 03:03:03 UTC, Andrei Alexandrescu wrote:
 * And if you really want to go meta, define metacode that can 
 take
 an AST node as a parameter and can visit the AST and figure 
 out what
 each node is. That would allow things such as loop fusion and 
 other
 advanced stuff. But for now, let's leave those aside.
hoooooooo :P
Jul 07 2013