Listening To Reason

random musings about technologies by Andy Norris

23 August 2006

I want first-class functions with my c#

With all of the cool functional improvements to the c# language in 2.0 and 3... uh... 3.5, it seems like it's about time for c# to leave the kingdom of nouns and hop the express train to having first-class functions. We have delegates, anonymous functions, continuations, and lots of other great functional elements in the language, but we don't have functions that can stand on their own, without having a class as a crutch.

Here's what I want:


public function int Foo(int bar) {
  return bar * bar;
}

int baz = Foo(42);
That's not asking all that much, is it?

But I thought everything was supposed to be an object!

So don't these insidious little functions just muck up the works for everyone? They don't even have classes! What the heck is that about?

Well, here's the thing. It's already possible to write the above code sample in c# -- it's just ugly and borked:


public static class Foo {
  public static int Invoke (int bar) {
    return bar * bar;
  }
}

int baz = Foo.Invoke(42);

It might be a little homely, but there's nothing evil or insidious about it, right? It's just a plain old static method. And really, is it more homely than a Factory or Strategy pattern?

Why would anyone in their right mind prefer


public abstract class SortStrategy {
  public abstract void Sort (int[] items);
}

public class QuickSortStrategy : SortStrategy {
  public QuickSortStrategy() 
  {
    // don't do anything here because this object is totally useless
  }

  public override void Sort (int[] items) {
    ...
  }
}

SortStrategy sorter = new QuickSortStrategy();
int[] myarray = { 1, 3, 7, 4, 2 };
sorter.Sort(myarray);

to


public delegate void Sort(int[] items);

public function void QuickSort(int[] items) {
  ...
}

Sort sortfn = QuickSort;
int[] mylist = { 1, 3, 7, 4, 2 };
sortfn(mylist);

And yes, there are already more concise ways to represent this in c# than by using an actual strategy pattern. For example, you could use the same syntax I used up above with Foo.Invoke:


public delegate void Sort(int[] items);

public static class QuickSort {
  public static void Sort (int[] items) {
    ...
  }
}

Sort sortfn = QuickSort.Sort;
int[] mylist = { 1, 3, 7, 4, 2 };
sortfn(mylist);

This is mostly as good as having the ability to declare a function. Here's the thing, though: if you're just using a class as a container for declaring a function, why bother? Just write it as a damn function, and be done with it.

It would be an easy piece of syntactic sugar to add to the language -- as far as the CTS is concerned, it could bytecode compile to Foo.Invoke anyway. We've come so far with the functional capabilities of c#, I just want to finish the job.

Tags: , ,