Did you already try to measure the impaired overhead of a wrapper solution? It might very well be negligible in an otherwise purely symbolic computation. A hybrid solution might be - instead of wrapping each value - to add a single method to the value classes that wraps a value on the fly if needed, e.g. Integer>>asExpression ^ExpressionWrapper wrap: self. If the expression protocol is invoked only rarely on the pure values, this solution reduces the overhead while keeping the value classes clean of foreign methods. Another option might be to build a trait that adds the behavior to the value classes. Best, Steffen Am .12.2018, 09:29 Uhr, schrieb Konrad Hinsen <konrad.hinsen@fastmail.net>:
Richard Sargent <richard.sargent@gemtalksystems.com> writes:
I understand your desire to utilize the existing Smalltalk mechanisms. But, I think the most important thing is modelling consistency.
What are the behaviours you expect from Expression, SumExpression, and ProductExpression? Do they know their parent expression? Their children? Other things?
I certainly agree that this should be the main consideration, but in my case that's done. Each Expression subclass stored its own specific information, which for leaf nodes such as integer expressions is really just a value. All I need is integers with added behavior.
I think that, in general, you will benefit from fully and consistently modelling the parse tree.
I should have mentioned that my Expressions are not parse trees. They are used as values in symbolic computation. They are constructed and deconstructed all the time, which is one reason I want to eliminate overhead, the other reason being clarity of code.
Konrad.