September 27, 2021

I sometimes feel that D is a bit weak when it comes to representing and handling dynamic tree-like data. However, I goofed around a bit and found that the newly added std.sumtype can get D quite far in that regard:

import std.sumtype;
alias Node = SumType!(string, This[]);
Node node(T...)(T args){
    auto result = new Node[args.length];
    foreach(i, arg; args) result[i] = arg;
    return Node(result);
}

void print(Node n){
    import std.algorithm, std.stdio;
    n.match!(
        (string s) => write(s, " "),
        (Node[] ns){"[".write; ns.each!print; "] ".write;}
    );
}
void main(){
    node(
        "top-level", node("subtree", node("with", "a", "subsubtree")),
        node, node, node // three empty elements
    ).print;
}
September 27, 2021

On Monday, 27 September 2021 at 18:21:24 UTC, Dukc wrote:

>

I sometimes feel that D is a bit weak when it comes to representing and handling dynamic tree-like data. However, I goofed around a bit and found that the newly added std.sumtype can get D quite far in that regard:

Nice. The tradition of sumtypes comes through ML (Meta-Language, not Machine Learning) and later FP langs, which always have tutorial topics like "test if a tree is a Braun tree" and "write an evaluator for an expression type"

# type expression =
      Const of float
    | Var of string
    | Sum of expression * expression    (* e1 + e2 *)
    | Diff of expression * expression   (* e1 - e2 *)
    | Prod of expression * expression   (* e1 * e2 *)
    | Quot of expression * expression   (* e1 / e2 *)

so it's natural that these would translate to D. The different style makes some definitions more verbose

// from std.sumtype docs
enum Op : string
{
    Plus  = "+",
    Minus = "-",
    Times = "*",
    Div   = "/"
}
alias Expr = SumType!(
    double,
    string,
    Tuple!(Op, "op", This*, "lhs", This*, "rhs")
);

but they still work. It'd be weird if trivial examples were very difficult :)