Jonathan:
I come from Haskell, so please excuse any functional
programming idiosyncracies I have :)
Welcome. You are the first Haskell programmer that I know willing
to learn and try D :-)
In Haskell, I have a datatype for representing so called terms
which looks like:
data Term = Var Char | Op Char [Term]
i.e. a Term is a variable (denoted by an Int) or an operation
(whose name is also denoted by an int), applied to a list of
its arguments. For example,
f(g(x,y),a(),x) is represented by Op 'f' [Op 'g' [Var
'x',Var 'y'],Op 'a' [], Var 'x]
In almost-theory D should allow code like:
import std.stdio, std.typecons, std.variant;
alias Term = Algebraic!(string, Tuple!(string, This[]));
void main() {
const expr = Term(tuple("f", [Term(tuple("g", ["x".Term,
"y".Term])), Term(tuple("a", [])), "x".Term]));
}
In practice std.variant module needs a This defined as "struct
This {}", plus another improvement to support recursive types
better, so that code doesn't work.
That code also can't work because the second type of the
"tuple("a", [])" literal is void[], so it's not compatible.
I am not sure a good enough library-defined Algebraic type can be
defined.
Okay, so the first thing I need to do is represent this as a
data structure in D. My choices are to represent the structure
as a class or as a struct. I choose struct because it is
simpler (in terms of what is going on), and because the entire
program takes one struct and makes changes to it.
Raw pointers are like razors, they can be useful, but they should
must also handled with a good amount of discipline and safeties
added by you and your experience, otherwise you cut yourself
often.
For a first version of your code you can try to use class
instances instead, that are easer to handle (especially in
garbage-collected language. But don't forget to add to functions
all the pre-conditions to assert the class references are not
null).
I see tons of things that can be improved in your code. Like the
switch, "(*term).node", the lack of immutable/const/pure/nothrow
(you should be able to write good enough functional code in D),
but better to think about the larger things first.
Bye,
bearophile