Pages

Friday, April 30, 2010

C# Dynamic

C# Dynamic


Although I think that a strong typed object oriented language should remain like this, and dynamic keyword in object oriented scenarios is a big mistake. Hoverer since NET 3.5 C# has the addition of functional languages called Lambdas, and I think that it's a great addition to the language as I use it constantly and with anonymous methods and delegates it's even better, but it wasn't really a true Lambda Calculus, some things like Curry function was very limited, but now we have C# 4.0 and the dynamic keyword, that's just great for functional programming.

Before I start any examples I would like to stress this out, that dynamic in object oriented scenario is bad, but when combined with functional it's a nice addition (more in scientific sense, as I don't see myself using a true lambda calculus in production environment).

In my article about anonymous methods, I introduced a function named curry, but in C# 3.5 it wasn't so effective, well it was but now we can take it to a new level.

So lets create a curry function:

/// <summary>
/// the basic Curry function.
/// </summary>
/// <param name="num">num.</param>
/// <returns>List of System Func dynamic dynamic.</returns>
public static Func<dynamic, dynamic> Curry(int num)
{
    int acc = num;

    return delegate(dynamic dyn)
    {
        if (dyn is Func<dynamic, dynamic>)
        {
            return dyn(acc);
        }

        acc += dyn;
        return acc;
    };
}

The interesting thing here is that we can check if 'dyn' is a delegate and the invoke it without knowing the type.

So now let's use the more dynamic version of the curry function:

Func<dynamic,dynamic> fun1 = Program.Curry(1);
Func<dynamic,dynamic> fun2 = Program.Curry(2);
var res = Program.Curry(3)(fun1(fun2)); //6

The result of the function is 6, but whats more interesting that now we can create a higher order functions, meaning that fun1 can invoke another delegate so can fun2 and those function results are being added.

But there's a better way to define such function, and the usage will be more intuitive, so let's do that now:

/// <summary>
/// the Curry2 function that utilizes the dynamic keyword.
/// </summary>
/// <param name="num">num.</param>
/// <returns>List of System Func dynamic dynamic.</returns>
public static Func<dynamic, dynamic> Curry2(int num)
{
    int acc = num;

    return delegate(dynamic dyn)
    {
        if (dyn is bool)
        {
            return acc;
        }

        acc += dyn;
        return new Func<dynamic, dynamic>(Curry2(acc));
    };
}

Now this function will return a new delegate of itself each time it is invoked, but that way we would always end up with a delegate so to stop the sums I decided to pass a bool, so if we have a bool then we return out accumulated value.

var result = Program.Curry2(1)(2)(4)(5)(10)(false); //22
Func<dynamic, dynamic> fun3 = Program.Curry2(1)(2);
var result2 = fun3(1)(5)(false); //9

Now this version is more useful, and clean.

C# has the ability to provide optional parameters, so the examples that I provided here can be updated, by using optional parameters in delegates, and the result of that would be super cool :-)

I'l show you, but let's do a new example using the dynamic, lambdas, and optional parameters. Lets do a sequence generator, for e.g the Fibonacci sequence, of course we could do a method that would act as a any generator of any desired sequence.

So let's define a simple Sequence Delegate with dynamic optional parameter:

/// <summary>
/// Simple sequence generator delegate.
/// </summary>
/// <param name="predicate"></param>
/// <returns></returns>
public delegate dynamic SequenceFunction(dynamic predicate = null);

Note: dynamic may only be null to be optional.

Not it's time to define our function:

/// <summary>
/// the Fib.
/// </summary>
/// <param name="num">num.</param>
/// <returns>List of System Func dynamic.</returns>
public static SequenceFunction Fib(int num = 1)
{
    int acc = num;

    return delegate(dynamic go)
    {
        acc += num;
        return new SequenceFunction(Fibx(acc, num));
    };
}

/// <summary>
/// the Fibx.
/// </summary>
/// <param name="current">current.</param>
/// <param name="prev">prev.</param>
/// <returns>List of System Func dynamic.</returns>
private static SequenceFunction Fibx(int current, int prev)
{
    return delegate(dynamic go)
    {
        if (go != null)
        {
            return current;
        }

        int tmp = current;
        current += prev;
        return new SequenceFunction(Fibx(current, tmp));
    };
}

The fib function will stop on some non optional argument, and once we give a starting param for our sequence generator we will actually get a private function Fibx that generates the values, now this brings us to another interesting topic that I will not cover now, but do you see it? :-) we can return a private function in a delegate and the consumer can use this function.

Now let's see what are the benefit's of using such implementation.

//clasic fib start at 1.
var fibResult = Program.Fib(1)()()()()()(true); //13

//now start at 2.
dynamic fibSeq = Program.Fib(2)();
var fibSeqResult = fibSeq()()()(true); //16

And we have a very nice sequence generator, now think of the possibilities with more complex real world examples. Probably in my next article I will expand this topic and add more details, but for now that is all.

In conclusion the dynamic keyword made C# not more dynamic but more functional I would say, now we have a a fully functional language at our hands, and that is actually a good thing :-).

No comments:

 
ranktrackr.net