That is one crazy Func! I think I’ll call it CrazyFunc.

Man, I am really having a creative dry spell. I have seriously started like three different blog posts at different points throughout the day today and gotten stuck each time! But in the interest of not totally failing in my goal of a blog post every day in 2011, I guess I’ll reveal the solution to my latest pop quiz since I did, after all, present it a full ten days ago.

The challenge, in case you don’t remember, was this:

Can you define a function in C# [I’m not sure why I saw the need to specify the language. -Dan] that takes a different function as input, and returns an instance of a delegate that will execute the input function and return an instance of itself?

The funny thing about this challenge is… technically, I guess my honest answer would have to be no; but that’s only because I didn’t phrase the question particularly well. What I can do, however, is write a function that will define such a function for me. I know—crazy, right? The trick, first of all, is to realize that this is simply not possible using one of the built-in delegate types from the BCL. A Func<T>, for example, cannot return a Func<T>; it has to return a T (you could try going with Func<Func<T>>, but it should be obvious after only a second or two that that’s not any better).

How do we get around this? We define our own delegate type that does return an instance of itself. It’s kinda like a Func<T>… only crazier. Let’s call it a CrazyFunc<T>.

delegate CrazyFunc<T> CrazyFunc<T>(T input);

That’s right, I did just go there.

OK, so how can we actually use this? Recall that the syntax proposed as part of the challenge would look something like this:

crazyFunc("What")("the")("heck?");

How do we actually write out an expression that will act in this way? Can you believe that the answer is using recursion?

Mwahahaha, yes. Using recursion.

static CrazyFunc<T> CreateCrazyFunc<T>(Action<T> sideEffects)
{
    return input =>
    {
        sideEffects(input);
        return CreateCrazyFunc(sideEffects);
    }
}

And voilà! Now we can write code like this:

CrazyFunc<string> crazyFunc = CreateCrazyFunc<string>(Console.WriteLine);
crazyFunc("Aaa")("aa")("a")("aAAaa")("aag")("ggGGGgh")("h")("hhh!!!")("!");

Output:

Aaa
aa
a
aAAaa
aag
ggGGGgh
h
hhh!!!
!

(Full disclosure: I originally encountered this problem because the user Juliet posted it—apparently for her own amusement—on Stack Overflow. I just liked it a lot, so I figured I’d share it with the world. And yes, I did post an answer of my own even though it wasn’t F#.)

Advertisements

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

%d bloggers like this: