As a learning exercise, I'm writing a simple AST evaluator for arithmetic expressions in D. (See https://gist.github.com/ckirkendall/2934374) In order to get a feel for functional programming in D, I decided to try and implement my solution in a functional style, using algebraic data types and pure functions.

Here's the code:

import std.variant;
import std.typecons;

enum Op { Plus, Minus, Times, Div }

alias Expr = Algebraic!(
    double,
    string,
    Tuple!(Op, "op", This*, "lhs", This*, "rhs")
);


double eval(Expr expr, double[string] env) pure {
    return expr.visit!(
        (double x) pure => x,
        (string v) pure => env[v],
        (Tuple!(Op, "op", Expr*, "lhs", Expr*, "rhs") bop) pure {
            final switch (bop.op) with (Op) {
            case Plus:
                return eval(*bop.lhs, env) + eval(*bop.rhs, env);
                break;
            case Minus:
                return eval(*bop.lhs, env) - eval(*bop.rhs, env);
                break;
            case Times:
                return eval(*bop.lhs, env) * eval(*bop.rhs, env);
                break;
            case Div:
                return eval(*bop.lhs, env) / eval(*bop.rhs, env);
                break;
            }
        }
    )();
}

When I compile this (using DMD 2.069 on Debian Linux), I get an error saying that I can't call visit from a pure function. This is surprising, since all visit does (in theory) is call the provided functions, and all of _them_ are pure.

My question is, is this an unavoidable limitation of visit's implementation, or is there a way to work around this?

Reply via email to