Can you write code for polymorphic tree structure separately with traits?


#1

I’ve got Java and C++ background. For example, I’ve got following tree structure (pseudocode):

  • class Expression
  • class Addition { Expression left, right }
  • class Multiplication { Expression left, right }
  • class FunctionCall { String name; Vector arguments }
  • and, so on…

And, I would like to write:

  • Number evaluate(Expression e)
  • String print(Expression e)

Is it possible to write separate code for evaluate and print functions with possibility to easily add new Expression types as 3rd party extension?

In, Java I need to put it together:

PrintResult {
   // indicates, whether to add parenthesis
   // ie. "1 + 3" must be wrapped with multiplication of 2:
   //  "(1 + 3) * 2"
   int resultPrecedence;
   String str;
}

Expression {
   Number evaluate();
   PrintResult print();
}

And, if I wanted to add a new operation, then I would need to just implement a custom Expression class. And, I can do it without touching original source/library.

Is it possible to do it with traits? And, is it possible to somehow separate the code? Because if not, then there’s no gain in traits IMO.


#2

This is my best interpretation of what you are asking for.
https://is.gd/K8etun


#3

I would suggest this: https://is.gd/k2vKaB

There’s a mostly 1:1 correspondence with Java concepts: the trait is an interface, the structs are classes implementing that interface. Extending the set of expressions is just adding another struct and trait impl.

The only slightly tricky corner is FunctionCall - that requires using Box for the arguments to allow the argument list to be runtime-polymorphic.

A print method can be implemented in a very similar way to how my example implements eval, although I agree with tupshin that you should consider using the existing Debug or Display traits instead.