sklose / NCalc2

expression evaluator for .NET with built-in compiler
MIT License
166 stars 58 forks source link

Allow to operate on System.Linq.Expressions.Expression #89

Closed eugenca closed 5 months ago

eugenca commented 6 months ago

Currently Expression.ToLambda returns Func<> Intermediate expression is hidden and not avaiable to touch LambdaExpressionVistor is internal

I need a way to use generated System.Linq.Expressions.Expression for my needs Thank you.

eugenca commented 6 months ago

If you provide appropriate way on how to achieve this, I could make merge request

david-brink-talogy commented 6 months ago

Can you explain your use case? The things you've listed seem like they're what's blocking you from achieving something, but I'd like to know what you want to do.

eugenca commented 6 months ago

Hi My use case it to get intermediate System.Linq.Expressions.Expression if I need Currently I can get only NCalc2.Expression or Func<> I need this to pass to optimizator of System.Linq.Expressions.Expression if I need

eugenca commented 6 months ago

Currently I solved it by forking and changing LambdaExpressionVistor to public, duplication ToLambda method on my side to obtain intermediate result

sklose commented 5 months ago

We could easily have another function on Expression that returns the ExpressionTree one step short of compiling it. However, I don't full understand the use case for it. You mentioned something about an optimizer, could you elaborate on that? In general I would consider it a bug if our lambda isn't optimal, and I'd rather ensure we generate an optimal lambda instead of adding the function that gives you access to the underlying ExpressionTree.

eugenca commented 5 months ago

Here is my test project, where you can check the behavior of generated expression online https://eugenca.github.io/wasm_projects/runge-kutta/ This is my setup: image On screenshot you could see parameters used to make execution for about 1000ms, and formula. In dev console you may see that formula contains additions to context variable, which are not optimized after compilation. (see "expression: ((((ctx.x + 2) + 2) + 2) + 2)" string) I used https://github.com/Thorium/Linq.Expression.Optimizer to optimize it. The issue I spotted was the fact that formula x+100 is faster than identical formula x+2+2+2 ... +2+2 (50 times +2)

eugenca commented 5 months ago

however formula 2+2+ ... +2 is as fast as 100

eugenca commented 5 months ago

So in my opinion, optional access to generation of System.Linq.Expressions.Expression may be useful in this or different cases if someone needed

sklose commented 5 months ago

I think it might be valuable to take a dependency on Thorium/Linq.Expression.Optimizer and have it optimize all lambdas. Would be curious to see

We can in addition add another API that exposes the ExpressionTree to the user.

happy to review a PR if you wanna give it a go @eugenca

eugenca commented 5 months ago

I would add function to expose System.Linq.Expressions.Expression

eugenca commented 5 months ago

https://github.com/sklose/NCalc2/pull/92