Pages

Monday, May 3, 2010

C# Dynamic

C# Dynamic Part 2

The first part is here.

As mentioned I will go back to dynamic and create something we could call a pseudo expression evaluator using dynamic keyword, just for fun and education purposes as I feel that this concept could be taken very far, for e.g we could create some custom expression evaluator that's only valid in some context in some class etc, it would look like a strong typed language but with no lexers or parses just delegates :-).

To some extent this is just a Curry function but with more control, over the currying process.

/// <summary>
/// Math Expr Evaluator.
/// </summary>
/// <param name="operatorParameter">operatorParameter.</param>
/// <param name="argument">argument.</param>
/// <returns>List of System Func dynamic dynamic dynamic.</returns>
public static Func<dynamic, dynamic, dynamic> 
    MathExpr(dynamic operatorParameter, dynamic argument)
{        
    return delegate(dynamic op, dynamic arg)
    {
        dynamic opRes1 = operatorParameter(argument, 0);
        dynamic opRes2 = op(arg, opRes1);

        return new Func<dynamic, dynamic, dynamic>(MathExprInternal(op, opRes2));
    };
}

/// <summary>
/// Math Expr Evaluator Internal.
/// </summary>
/// <param name="operatorParameter">operatorParameter.</param>
/// <param name="argument">argument.</param>
/// <returns>List of System Func dynamic dynamic dynamic.</returns>
private static Func<dynamic, dynamic, dynamic> 
    MathExprInternal(dynamic operatorParameter, dynamic argument)
{
    return delegate(dynamic op, dynamic arg)
    {
        if (op == null)
        {
            return argument;
        }

        argument = op(arg, argument);
        return new Func<dynamic, dynamic, dynamic>(MathExprInternal(op, argument));
    };
}

Straight forward so far, the code is very simple and short, as we just want a simple math evaluator just for fun, the key thing here is that one of our arguments to delegate will be another delegate that we will invoke with our argument parameter, thus with each delegate call we will accumulate the value.

So now let us define some delegates that do operations on he arg and the argument:

var Cout = new Func<dynamic, dynamic, dynamic>((x, y) => { Console.WriteLine(y); return y; });
var Print = new Func<dynamic, dynamic, dynamic>((x, y) => { Console.WriteLine(x); return y; });

var Add = new Func<dynamic, dynamic, dynamic>((x, y) => x + y);
var Sub = new Func<dynamic, dynamic, dynamic>((x, y) => x * -1 + y);
var Mul = new Func<dynamic, dynamic, dynamic>((x, y) => x * y);
var Div = new Func<dynamic, dynamic, dynamic>((x, y) => y / x);
var Cin = new Func<dynamic, dynamic, dynamic>((x, y) => y = x);
var Nop = new Func<dynamic, dynamic, dynamic>((x, y) => y);

Some basic functions to get our math evaluator going, along with Cout and Print, Cin, and Nop ;-).

Now let's test it.

Program.MathExpr(Add, 5)(Mul, 2)(Div, 2)(Cout, null)(Add, 1)(Cin, 11)(Cout, null)(Print, "hello");

How to interpret what we just did?. We apply the function to a delegate and pass the value as an argument to that function, and then accumulate the result. Cout gives us the result, and Cin overrides the current result with the value in the argument.

So with almost no work at all we just did something that looks like an abstract language evaluator.

No comments:

 
ranktrackr.net