2

Basically I am trying to multiply two lambdas with the class Expression but I don't even manage to build and can't find documentation on this. Here is my code:

var f = x=>x+2;
var g = x=>x+3;
var argX = Expression.Parameter(typeof(double), "x");
var fg = Expression.Multiply(Expression.Constant(g, typeof(Func<double, double>)), Expression.Constant(f, typeof(Func<double, double>)));
//var fg = Expression.Multiply(Expression.Constant(g),Expression.Constant(f));
var lambda = Expression.Lambda<Func<double, double>>(f3, argX);
return lambda.Compile();
V.Leymarie
  • 2,708
  • 2
  • 11
  • 18
  • 1
    What does it even mean to multiply two functions? You can multiply *values*, but not *functions*. – Servy Dec 07 '16 at 15:44
  • And if you're just going to compile your expressions into delegates, why deal with expressions in the first place? Just deal with delegates from the start. – Servy Dec 07 '16 at 15:45
  • A lambda returns a value and I want to multiply two lambdas. Basically I want something like x=>(x+2)*(x+3) Dealing with delegate would work for sure but is a bit slower according to this topic: http://stackoverflow.com/questions/5568294/compiled-c-sharp-lambda-expressions-performance – V.Leymarie Dec 07 '16 at 15:47
  • Is this some sort of a method? Can we see the actual method signature because what you have posted does not even compile. – Ivan Stoev Dec 07 '16 at 15:49
  • 1
    Like I said, multiplying two *lambdas* makes no sense. I know a lambda (can) return a value. You can multiply the results of executing two lambdas (if they're delegates) but that's very different than multiplying the lambdas themselves. You shouldn't be worrying about performance for something like this. First get it working, and then, if you notice performance problems, look at where your code is spending lots of time and consider how it could be improved. I'm quite confident that you're code is going to perform *worse* using expressions for stuff like this. – Servy Dec 07 '16 at 15:51
  • Not to forget the maintainance-nightmare you produce when writing such complicated code. Honestly: focus on working code, make optimization if it is neccessary. **Premature optimization is the root of all evil**. – MakePeaceGreatAgain Dec 07 '16 at 15:54
  • Thank you guys, but I am working on a pretty sensible code and performances are at the very center of my work. I simplified the problem here, but what I would like is just compile into a delegate the product of my two lambdas (which are delegates, they are Func) in order to get a final Func x=>(x+2)*(x+3) – V.Leymarie Dec 07 '16 at 15:58
  • 1
    Okay, but that does not apply to "multiplying lambdas", but simply "create a lambda which is the result of one number multiplied another number". So I suppose both `f` and `g` needs to be expressions also. – MakePeaceGreatAgain Dec 07 '16 at 15:59
  • 1
    @V.Leymarie If you care about performance then you almost certainly *don't* want to use expressions. It will virtually certainly make the code perform worse. If you're accepting two delegates, then *say* that you're accepting two delegates. That's *highly* relevant to the question. Additionally, if you want to create a new delegate that represents invoking two other delegates with its parameter and multiplying the results then *ask that* rather than asking how to multiple delegates, because you don't multiply delegates, you multiple *values*, that (in this case) were provided by a delegate. – Servy Dec 07 '16 at 16:12
  • 1
    @V.Leymarie At the end, what really is the type of `f` and `g` - `Expression>` or `Func`? – Ivan Stoev Dec 07 '16 at 16:21

2 Answers2

4

Do you want something like this:

Expression<Func<double,double>> f = x => x + 2;
Expression<Func<double,double>> g = x => x + 3;

var param = Expression.Parameter(typeof(double));
var invokeF = Expression.Invoke(f, param);
var invokeG = Expression.Invoke(g, param);

var mult = Expression.Multiply(invokeF,invokeG);

var lambda = ((Expression<Func<double, double>>)Expression.Lambda(mult, param)).Compile();

If i call it this way:

lambda(3);

I get 30 as valid answer.

Maksim Simkin
  • 9,561
  • 4
  • 36
  • 49
  • I'd change the lambda line a bit to directly compile it: `var lambda = (Func) Expression.Lambda(mult, param).Compile();` Then you can skip the `Compile()` call when you want to use it later. – fknx Dec 07 '16 at 16:14
0

For this simply define f and g as Expression as well:

var argX = Expression.Parameter(typeof(double), "x");

var f = Expression.Add(argX, Expression.Constant(3.0)); // applies to x => x + 3
var g = Expression.Add(argX, Expression.Constant(2.0)); // applies to x => x + 2
var fg = Expression.Multiply(f, g); // applies to f(x) * g(x)
var lambda = Expression.Lambda<Func<double, double>>(fg, argX);

Now call it like this:

var r = lambda.Compile()(1);

Which returns 12.

MakePeaceGreatAgain
  • 35,491
  • 6
  • 60
  • 111