Expression Tree question

Nov 15, 2007 at 6:41 PM
Howdy,

Thanks again for all your answers so far.

In your pre-Flee stuff, there is an AddFormula method which allows me to add a named expression (such as 1 + 1 or x - y). This is super useful to us, and FormulaEngine will give us a lovely error message if things are out of place.

It looks like this:

formulaEngine.AddFormula("X", "1 + 1")

It's not obvious to me whether or not I can do this with Flee. Is it possible? All your examples Flee use SetVariable.

Thanks a lot,
Dustin
Coordinator
Nov 15, 2007 at 10:15 PM
Edited Nov 15, 2007 at 10:17 PM
Hi Dustin,

The CalculationEngine lets you do this, you just go about it in a more indirect way due to the way Flee works:

// Create the calculation engine
CalculationEngine engine = new CalculationEngine();
ExpressionContext context = new ExpressionContext();
// Set the calculation engine on the context
context.CalculationEngine = engine;
 
// Set the expression name
context.ExpressionName = "x";
// Compile it, at which point it will get added to the calculation engine at the name "x"
ExpressionFactory.CreateDynamic("1 + 1", context);
 
object result = engine.GetResult("x");
Nov 15, 2007 at 11:00 PM
Hi Eugene,

Thanks a lot. I didn't realize that the ExpressionContext works that way. So there is one expression context for each expression.

I'm loving the framework, so please don't take this as criticism, but that seems like a lot of code to replace the old AddFormula("x", "1 + 1")

With that said, much appreciated. I'm going to give that a whirl.
Coordinator
Nov 16, 2007 at 3:42 AM
Yeah, I agree that it's not an elegant way of doing it. I was trying to come up with a more elegant method than the old way I was doing it, but I think just using an Add method on the calculation engine is the best way.

I'll put in the change in the next release.

>So there is one expression context for each expression.
The expression context holds all the information required to create an expression: variables, imports, and options.
Nov 16, 2007 at 3:51 PM
Hi Eugene,

Another way we were thinking that might be a nice blend between the two is to leave it the way it is for flexibility but add a new constructor to ExpressionContext.

So this code:

CalculationEngine engine = new CalculationEngine();
 
ExpressionContext contextA= new ExpressionContext();
            
contextA.CalculationEngine = engine;
            
contextA.ExpressionName = "a";
            
ExpressionFactory.CreateDynamic("500", contextA);

Would turn into this code:

CalculationEngine engine = new CalculationEngine();
 
ExpressionContext contextA= new ExpressionContext(engine, "a", "500");

I think your engine is amazing and I have a feeling developers from the financial sector would find it very interesting. One thing you might want to consider if you get a large fan base is to keep the API somewhat backwards compatible so users don't have to change their code TOO often.

Anyway, thanks.
Nov 16, 2007 at 4:00 PM
Hi Eugene,

I take that back, what I said above. I don't think that constructor is a good idea. It's too hard to tell what it's doing in there.

We've wrapped the code that adds an expression anyway, so if it takes a few lines to make it more flexible then who cares. A helper method somewhere might make sense, but only because I think the current code isn't that easy to figure out without help.
Coordinator
Nov 16, 2007 at 11:00 PM
I think the current way is confusing as compiling an expression with a name has a hidden side-effect of adding it to the calculation engine. I did it that way so that I wouldn't have to provide a CalculationEngine.Add method for all the ways of creating an expression (with/without owner, generic/dynamic). It turns out in the end, the engine can only use one type of expression anyways, so I should just stick to the more intuitive Add method.