Super-dee-duper D features
Kevin Bealer
kevinbealer at gmail.com
Mon Feb 12 01:05:12 PST 2007
Great post; all of this is interesting, and I think I agree with all of
the individual points.
Walter Bright wrote:
> kris wrote:
...
>
> Some comments:
...
> 4) The more experience I have, the more it seems that the language that
> got a lot right is ... Lisp. But Lisp did one thing terribly, terribly
> wrong - the syntax. The Lisp experts who can get past that seem to be
> amazingly productive with Lisp. The rest of us will remain envious of
> what Lisp can do, but will never use it.
>
> 5) Lisp gets things right, according to what I've read from heavy Lisp
> users, by being a language that can be modified on the fly to suit the
> task at hand, in other words, by having a customizable language one can
> achieve dramatic productivity gains.
Yes - I've often wished for Ocaml or LISP with C syntax, but LISP has
another real issue to me, which is that 'mutable' algorithms are hard.
> 6) If I think about it a certain way, it looks like what C++ Boost is
> doing is a desperate attempt to add Lisp-like features. By desperate I
> mean that C++'s core feature set is just inadequate to the task. For
> example, look at all the effort Boost has gone through to do a barely
> functioning implementation of tuples. Put tuples into the language
> properly, and all that nasty stuff just falls away like a roofer peeling
> off the old shingles.
...
> 9) But I see what C++ templates can do. So to me, the problem is to
> design templates in such a way that they are as simple to write as
> ordinary functions. *Then*, what templates can do can be accessible and
> maintainable. It's like cars - they used to be very difficult to drive,
> but now anyone can hop in, turn the key, and go.
...
> 11) Today's way-out feature is tomorrow's pedestrian code. I'm old
> enough to remember when "structured code", i.e. while, for, switch
> instead of goto, was the way-out feature (70's). Then, OOP was all the
> rage (80's), now that's a major yawner. STL was then the way-out fad
> (90's), now that's pedestrian too. Now it's metaprogramming (00's), and
> I bet by 2015 that'll be ho-hum too, and it's D that's going to do it.
...
Code in C++ wants to be iterative/imperative, and code in LISP wants to
be recursive and functional. But the 'macro system' in both cases is
written as a functional / recursive system. In LISP, this was by design
and works with the language, in C++ its because recursion happened to
fit through a keyhole in the template grammer.
LISP makes it hard / awkward to work with large mutable structures.
Everything is functional so a functional macro system can do everything.
C++ templates were great (by today's standards, adequate) for container
classes, but that task could almost be done just with text substitution.
So...
In my view, to make metaprogramming work in a way that non-LISP people
understand in something like C++ or D, we need to see programs as a
series of iterations:
1. A program with all the static code, but main() is replaced by calls
to functions in each module that manufacture code (code factories).
2. Same as 1, with the newly manufactured code added, along with new
calls to code factories.
3. Same as 2, etc.
N. A program with all static (non-template) code.
Each step is run to produce the next step -- in most cases, this
consists of running one code generator after another -- the individual
steps are not actually explicit, but it is important for one code
generator to be able to use the results of another when it needs to.
All steps except N are optional, and usually you would have just 1 and
N. It might be a good idea at first to require that.
The difference between this world order and the current (C++) way, is
that in C++ the factories are defined as recursive templates that expand
like fractals.
Rationale:
LISP macros have access to essentially all of LISP. If they didn't have
access to (for instance) mapcar, the LISP macro system would be
measurably harmed.
D programs need the same consideration --- if a 'regular D' programmer
had to do without std.string, they would feel the absence every time he
needed find(). Similarly, every time I try to write a meta-program in D
today, I feel the same absence of std.string.
I think to really write clean code for the 'code factory' step, I need
to be able to write nested loops over the user input, accumulate code in
strings with "~=", and so on without writing it recursively.
My first thought on "how" is to build an interpreter in the compiler
that can run the parse tree of a D function. Which brings us fairly
close to the LISP domain, the primary difference being that this
interpreter would not necessarily be included in the compiled program
(i.e. its not 'eval()', yet.)
(Without having written a real working compiler, I don't know how
practical this is; I think I've heard of parse-tree based interpreters
in relation to perl. A reasonable restriction might be "no C calls".)
Kevin
More information about the Digitalmars-d
mailing list