Erlang Central

Erlang Funs and C Sharp

Revision as of 09:35, 2 September 2006 by Rvg (Talk | contribs)

One of the stranger things in Erlang for me was the concept of Funs. (Think Functions). According to the Erlang Documentation a fun is a functional object. In short it means that you can use a fun to assign code to a variable.

This is very useful. Imagine a scenario where you want to write the code now (because you have access to data, state or variables), but it should only be executed much later and by someone else. A typical use is to run a query which writes something to database, without returning something. Usually I prefer to have some other process (or thread) in a system take care of all database related functionality. You can then write a fun to execute the query and (possibly) process the result. You can achieve this with code that looks something like this:

 1: function() ->
 2:   V1 = "select * from my_table;",
 3:   F = fun() ->
 4:       Query = V1,
 5: 	  {ok,Result} = queryexecuter:execute(V1),
 6: 	  io:format("The result of the query is ~p\n",[Result]),
 7: 	  ok
 8:   end,
 9:   queryqueue:queue(F),
10:   ok.

The interesting part is lines 3 to 8. This creates a functional object named F. You can now pass F into the (fictional) queryqueue:queue() which presumably will queue the query and execute it at some time in the future. What is neat about this, is that the Fun made references to the variable V1 and used that later.

When the queryqueue executes the Fun, it would do something like this:

11: executequery(Fun) ->
12:   Result = Fun(), 
13:   ok.

The earlier Fun is passed as the parameter to executequery (line 11). It can then execute the fun simply by invoking it (line 12). At this time, our earlier fun will execute and print the result as in line 6

== C# Delegates ==

A delegate declaration defines a reference type that can be used to encapsulate a method with a specific signature. A delegate instance encapsulates a static or an instance method. Delegates are roughly similar to function pointers in C++; however, delegates are type-safe and secure. A delegate lets you pass a function as a parameter.

Look at the following delegate declaration:

public delegate int doCalculate(int aParam1, int aParam2);

It takes two integer parameters and return another integer. This is known as the signature of the delegate.

If you build a class:

 1:  public class Class1 {
 2:    public  doCalculate getDelegate() {
 3:      return new doCalculate(intMultiply);
 4:    }
 6:    private int intMultiply(int aParam1, int aParam2) {
 7:      return aParam1 * aParam2; 
 8:    }
 9:  }

You can use this class as follows

10: ...
11: Class1 myClass = new Class1();
12: doCalculate delegate = myClass.getDelegate();
13: ...
14: int result = delegate(12,4);
15: ...

As you can see, this is very similar to the Erlang Fun concept. To be very honest, you could achieve the same effect by declaring a simple one function interface and implementing that in Class1.

I prefer delegates to interfaces because you don't have to explicitly implement the interface in the class, so you are completely free of the naming conventions interfaces impose. It is completely possible to pass return two delegate instances from the same class and of the same type that point to two different internal functions.

The difference

In essence the two languages achieve the same thing through two very different mechanisms. In C# the delegate retains a reference to the original object, while in Erlang the Fun is completely detached from the call stack at the time of execution.

In Java, this is called the Command Pattern. Simply put, you pass an object extending an interface with an execute() method as argument to such a queue or something that will later invoke .execute() on it, without knowing anything about the object.

In C, the same can be achieved using a pointer to a function. Pass this function pointer around to the queue class and let it later invoke an .execute() method or similar.