Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What does Expression.Reduce() do?

I've been working with expression trees for a few days now and I'm curious to know what Expression.Reduce() does. The msdn documentation is not very helpful as it only states that it "reduces" the expression. Just in case, I tried an example (see below) to check if this method included mathematical reduction, but this doesn't seem to be the case.

Does anyone know what this method does and is it possible to provide a quick example showing it in action? Any good resources out there?

static void Main(string[] args) {     Expression<Func<double, double>> func = x => (x + x + x) + Math.Exp(x + x + x);     Console.WriteLine(func);     Expression r_func = func.Reduce();     Console.WriteLine(r_func); // This prints out the same as Console.WriteLine(func) } 
like image 987
d.. Avatar asked Jan 10 '10 21:01

d..


2 Answers

The document you need to look at is expr-tree-spec.pdf.

This is the specification for the expression trees. Read the "2.2 Reducible Nodes" and "4.3.5 Reduce Method" sections.

Basically, this method is intended for people implementing or porting their dynamic langauges to .NET. So that they can create their own nodes that can "reduce" to standard expression tree nodes and can be compiled. There are some "reducible" nodes in the expression trees API, but I don't know whether you can get any practical examples (since all standard expression nodes compile anyway, as the end-user you probably do not care whether they are "reduced" behind the scenes or not).

Yes, MSDN documentation is very basic in this area, because the main source of info and docs for language implementers is on GitHub, with the documentation in its own subfolder.

like image 127
Alexandra Rusina Avatar answered Sep 28 '22 04:09

Alexandra Rusina


With a little disassembling, I found that Expression.CanReduce always reutrns false and Expression.Reduce() always returns this. However, there are a few types that override both. LambdaExpression inherits the default implementations, which explains why the expressions that have been tried so far do not work.

One of the types that overrides Reduce() is MemberInitExpression, which led me to the following successful experiment:

class ReduceFinder : ExpressionVisitor {     public override Expression Visit(Expression node) {         if (node != null && node.CanReduce) {             var reduced = node.Reduce();             Console.WriteLine("Found expression to reduce!");             Console.WriteLine("Before: {0}: {1}", node.GetType().Name, node);             Console.WriteLine("After: {0}: {1}", reduced.GetType().Name, reduced);         }         return base.Visit(node);     } }  class Foo {     public int x;     public int y; }  static class Program {     static void Main() {         Expression<Func<int, Foo>> expr = z => new Foo { x = (z + 1), y = (z + 1) };         new ReduceFinder().Visit(expr);     } } 

Output:

Found expression to reduce!   Before: MemberInitExpression: new Foo() {x = (z + 1), y = (z + 1)}   After: ScopeN: { ... }   
like image 30
Nick Guerrera Avatar answered Sep 28 '22 03:09

Nick Guerrera