Joel Spolsky published an article around functional programming, and how it enables things like separating the logic that traverses a data structure, from the code that needs to perform some logic over each object in the data structure. He uses JavaScript, the ability to define anonymous functions and using them as parameter values in his samples to illustrate how it provides a better model compared to languages like Java. In his post, he asks "Can your programming language do this?" Check it out, and then come back here...
So, it turns out C# 2.0 already supports some degree of functional programming via anonymous delegates. C# doesn't just provide the ability to pass a function as a parameter value. The C# feature is built on top of the existing delegate infrastructure, which allows one to associate object (or "this") context with the function when needed for instance methods, as well as allow a compiler to check if the signature of your function matches the expected parameter type. I was not a huge fan of anonymous delegates, but things seem to have changed... a bit. I guess working with JavaScript for some time now has opened me somewhat to using them, esp. when they seem appropriate.
As a result, I just added support for anonymous delegates in Script# as well (as of build 0.1.4.0). I also added iteration APIs such as ForEach, Map, Filter, Some and Every on Array. For example, Map allows you to map each element of an array to some other computed value. Here is what Script# defines in its mscorlib equivalent, sscorlib.dll:
public delegate object ArrayItemMapCallback(object value, int index, Array array);
public delegate int CompareCallback(object x, object y);
public class Array {
public Array Map(ArrayItemMapCallback callback);
public void Sort(CompareCallback compareCallback);
}
Now I can write some code in my app as follows:
static int SortNumbers(object x, object y) { ... }
static void MyMethod() {
int[] values = new int[] { 3, 1, 2 };
values.Sort(new CompareCallback(SortNumbers));
int[] computedValues =
(int[])values.Map(delegate(object value, int index, Array array) {
return (int)value * (int)value;
});
}
This translates to the following JavaScript:
function sortNumbers(x, y) { ... }
function MyMethod() {
var values = [ 3, 1, 2 ];
values.Sort(Delegate.create(null, sortNumbers));
var computedValues = values.map(Delegate.create(null, function(value, index, array) {
return value * value;
});
}
The sample shows how you can use delegates to point to named member methods, as well as anonymous methods written inline within another function. Note that once I add generics support to Script#, this will be even more clearer when the casts all disappear. Personally, I like the strong typing associated with delegates; For example, I don't have to explicitly remember the signature and ordering of parameters in the callback method. Now the compiler can check if I am doing the right thing up front and do its job, rather than having to wade through runtime errors myself to tell me the same.
Script# doesn't limit usage of anonymous delegates to intrinsic JavaScript types such as Array. As you'd expect, you can use the anonymous delegate functionality anywhere you use delegates. The Script# runtime provides a light-weight implementation of Delegate written in JavaScript.
For example, one of the classes I provide in the Script# framework is HTTPRequest, which is an abstraction over XMLHttpRequest. The following is relevant bits of API it provides:
public delegate void HTTPRequestCompletedCallback(HTTPRequest request, object userContext);
public class HTTPRequest {
public static HTTPRequest Create(string uri, string verb);
public void Invoke(HTTPRequestCompletedCallback callback, object userContext);
}
Now, say I have an instance method in my application class, and inside that I could use the API as follows (this is based on one of the shipping samples):
private void Update() { ... }
void PerformRequest() {
HTTPRequest request = HTTPRequest.CreateRequest("MyService.ashx", "GET");
request.Invoke(delegate(HTTPRequest request, object context) {
string text = request.Response.Text;
this.Update();
}, null);
}
This gets translated to:
function update() { ... }
function performRequest() {
var request = ScriptFX.Net.HTTPRequest.createRequest("MyService.ashx", "GET");
request.invoke(Delegate.create(this, function(request, context) {
var text = request.get_response().get_text();
this.update();
}, null);
}
Notice the distinction from the previous sample; the anonymous delegate is defined inside an instance method rather than inside a static method. Hence the delegate is passed in the "this" context, and it can be used inside its body.
What do you think? Cool, huh? :-) These allow you to use some key functional aspects of functional programming in JavaScript even while using c# and script#. You can download the bits to try things out and follow future developments in Script# from my project page.
Quick heads up for existing Script# users:
In past builds, one needed to call Delegate.Unwrap on a delegate instance before passing it onto a native script API or into the DOM. As of build 0.1.4.1 (published today), you can now skip this step. A delegate is directly usable as a function. This has an additional benefit; where previously APIs on things like Array.Sort, DOMElement.AttachEvent took an untyped, generic Function instance, they now take strongly-typed delegates like CompareCallback, and DOMEventHandler.