Really silly things to do with C# expression trees

As you may remember from my last post I’m current reading Structure and Interpretation of Computer Programs as part of a study group we started during Pablo’s Fiesta.

I continue to find Lisp to be a fascinating language especially this really interesting piece of code.

(define (a-plus-abs-b a b)
      ((if (> b 0) + -) a b))

Ok so what’s going on here?

  • if b > 0
    • return +
  • else
    • return -

In my previous post I demonstrated how you might implement this in javascript. Well I found it so interesting that I decided to find out if I could do it in C# as well. The following is my attempt at trying to return the + or – symbol from an if statement.

[TestFixture]
public class ExpressionTreeFixture
{
    [Test]
    public void a_plus_abs_b_should_equal_9()
    {
        a_plus_abs_b(5, -4).ShouldEqual(9);
    }

    private int a_plus_abs_b(int a, int b)
    {

        var operation = b > 0 
            ? ExpressionType.Add 
            : ExpressionType.Subtract;

        var maths = Expression
                        .MakeBinary(operation, 
                                Expression.Constant(a),
                                Expression.Constant(b));

        return Expression.Lambda<Func<int>>(maths).Compile()();
    }
}

“Why would you write it this way when (insert code here) works better?”

Shut up troll! I’m not telling anybody to go off and write their code in expression trees when the following code is clear the correct why to write it.

        if (b > 0) return a + b;
        return a - b;

See that’s way easier, but this isn’t a post about smart things to do with expression trees now is it?

Let’s up the silliness some more and make it an extension method just for fun.

[TestFixture]
public class ExpressionTreeFixture
{
    [Test]
    public void a_plus_abs_b_should_equal_9()
    {
        5.PlusAbs(-4).ShouldEqual(9);
    }
}

public static class IntExtension
{
    public static int PlusAbs(this int a, int b)
    {
        var operation = b > 0 
            ? ExpressionType.Add 
            : ExpressionType.Subtract;

        var maths = Expression
            .MakeBinary(operation, 
                    Expression.Constant(a),
                    Expression.Constant(b));

        return Expression.Lambda<Func<int>>(maths).Compile()();
    }
}

I was having so much fun with this that I even roped some of my teammates in on it. Heres Chad Myers solution.

public int add(int a, int b)
{
    return a + b;
}

public int subtract(int a, int b)
{
    return a - b;
}

public Func<int, int> boo(int b)
{
    var plus = new Func<int, int>(a => add(a, b));
    var minus = new Func<int, int>(a => subtract(a, b));

    return (b > 0) ? plus : minus;
}

So I think its cool that you can kind of return + or – from an if statement, but what started as a fun little exercise turned into an amazing adventure into learning expression trees.

So as my final brain beating exercise I tried make this into a Func<int,int,int> completely build using expression trees.

public Func<int,int,int> a_plus_abs_b ()
{
    ParameterExpression a = Expression.Parameter(typeof (int), "a");
    ParameterExpression b = Expression.Parameter(typeof (int), "b");

    var greaterThanZero = Expression.MakeBinary(ExpressionType.GreaterThan, b, Expression.Constant(0));

    var maths = Expression.Condition(greaterThanZero, 
            Expression.MakeBinary(ExpressionType.Add, a, b),
            Expression.MakeBinary(ExpressionType.Subtract, a, b));


    return Expression.Lambda<Func<int, int, int>>(maths, a, b).Compile();
}

So here’s a little challenge. In the comment section I invite you to completely school me in the ways of Expression Trees. Try and come up with a way more awesome version of a_plus_abs_b using expression trees or IL or whatever awesome sauce is in the .NET framework that I’m not aware of.

Herp Derp,

-Ryan

Related Articles:

Post Footer automatically generated by Add Post Footer Plugin for wordpress.

About Ryan Rauh

My name is Ryan Rauh and I like shiny things. If I've seen it on twitter more the twice most likely I've looked at it or tried it. I really like memes and other silly and seemingly useless things out on the internet. I blog about things *I* think are cool and interesting, I hope you will find them cool and interesting too.
This entry was posted in Functional Programming and tagged , . Bookmark the permalink. Follow any comments here with the RSS feed for this post.
  • E.Z. Hart

    How about some ridiculous operator overloading?

    https://gist.github.com/1335363

    • Anonymous

      I’m not sure what you mean. Link me a gist

      EDIT: didn’t see the gist link in my email. Weird.

      That’s pretty awesome! I forgot you could overload operators for classes, too bad you can’t do that with out the Number class, but definitely cool thanks!

  • Daniel Marbach

    Hy
    I would wrap the expression compile with a lazy<func> so that you only need to compile once.

    @e.z. Hart
    You could also use implicit cast to int in your example. That would make it even easier to get the result or imlicit cast to the function delegate ;)

    Daniel

  • Sam Stephens

    This seems a fairly literal version of the Lisp code: https://gist.github.com/1335868

    • Anonymous

      Nice this seems a lot like chads example. I wasn’t aware the you could just cast a lambda like that 
      (Func) (x,y) => x + y

      Kind of interesting actually

  • http://twitter.com/sshishkin Sergey Shishkin

    That’s the reason C# sucks at functional programming. The closest thing to the original Lisp would be this mess:
    https://gist.github.com/1336143

    • Anonymous

      I really like how you composed the 
          
      cond ?  then : else 

      I know in lisp that you have to be careful because the (if  predicate then else) acts as a special construct that behaves slightly differently. 

      I like this method I want to see what will happen if you turned that into some kind of recursive function.  Something really contrived like adding the numbers by incrementing a while decrementing b

  • http://openid.thinkbeforecoding.com/jeremie.chassaing thinkbeforecoding

    You can also try F# here :

    let (++) a b = (if a > 0 then (+) else (-)) a b

    You can then use the infix operator ++ :
    3 ++ -5

    or : if you want an operator for if then else :
    let (!?) x f e = if x then f else e
    let (++) a b = (!? (b > 0) (+) (-)) a b

    Have F#un !

    • Anonymous

      That is really awesome! So you can return + or – in F#!

      Amazing how I can now read F# and know what its doing, functional FTW! SICP is opening my eyes a lot!

      BTW how did you post code in disqus like that?

      • http://openid.thinkbeforecoding.com/jeremie.chassaing thinkbeforecoding

        I made a copy through notepad :-P

        For the +, – and other operators  in F# there are two things:
        You can simply use it like in a + b, in this case, it is infixed, and you have to provide both operands.
        When using it between parentheses, it becomes a simple function, hence prefixed and curryable.

        You can define almost any operator like ??, |?, , +-, ~> by defining it between () like I did for ??.

        • Anonymous

          I actually kind of like the prefix notation. I hear thats what most people hate the most about Lisp

  • http://profiles.yahoo.com/u/XHP2LPHRJMLI25MBX7I3FZPE6M James C

    Chad & Sam seem to be on the right path,  but  both seem to go off in an odd direction. I think this combines simplicity, reusablity,  and comes closest to the original lisp code:

    https://gist.github.com/1336856

  • Anonymous

    Nice to see another RedditorProgrammer.

    Derp.

    • Anonymous

      LULZ, how could you tell :P