Is lambda a syntatic sugar, or Turkish delight?

1. January 2009

We had been discussing on twitter+gtalk if lambdas are syntatic sugar or not. According to wikipedia, a syntatic sugar is a term coined by Peter J. Landin for additions to the syntax of a computer language that do not affect its functionality but make it "sweeter" for humans to use. Based on this description, what I see is that: We could build up an expression tree with a bunch of method calls before c# 3.0, but now we have an easier way of building it. It was even possible to build an expression tree runtime (take a look at db4o native queries and mono project). Moreover, lambdas aren’t just for expressions but also they can be converted into delegates.

Let’s do some demonstration now:

Action<MyClass> myAction=x=>x.Increment();


This piece of code is translated into following code

private static void Main(string[] args)
{
    Action<MyClass> myAction = (CS$<>9__CachedAnonymousMethodDelegate1 != null) ? CS$<>9__CachedAnonymousMethodDelegate1 : (CS$<>9__CachedAnonymousMethodDelegate1 = new Action<MyClass>(Program.<Main>b__0));
}

(Please note that our lambda has been converted into another ordinary method at compile time)
This code could have been written using ordinary C# syntax.

As you know, Lambas can also be converted into an expression depending on the context:

Expression<Action<MyClass>> myExpression = x => x.Increment();


This one, for example, will be translated into

private static void Main(string[] args)
{
    ParameterExpression CS$0$0000;
    Expression<Action<MyClass>> myExpression = Expression.Lambda<Action<MyClass>>(Expression.Call(CS$0$0000 = Expression.Parameter(typeof(MyClass), "x"), (MethodInfo) methodof(MyClass.Increment), new Expression[0]), new ParameterExpression[] { CS$0$0000 });
}


Now instead of into method/delegate, lambda has been converted into an expression, which can be done using an existing C# syntax.
One thing to note, Lambda itself has nothing to do with expressions. They can be converted into Expressions and then it is a piece of code that make something with those expressions (means that expressions can be interpreted by some providers) but it is a _short cut_ of doing it.

After those examples, one of my friends told that if we are talking about IL/CLR syntatical sugars, then they would agree. We can also extend this statement into “any programming language other than assembly (or basically 101001000s) is a syntatical sugar.” I would have agreed if I hadn’t known the definition of programming language.

For me, the syntatical sugars of C# language are the followings:
  1. The using statement
  2. The var keyword
  3. Lambdas
  4. Anonymous methods
  5. The dynamic keyword
  6. Automatic properties
  7. Object/Collection initializers

On the other hand, Generics, for example, is not a syntatical sugar. It doesn’t fall into another code within the same language. I am not sure about if this definition is valid, but this is the way I think it.

Just my 2 ykrs, I am trying to draw the boundaries of a syntatical sugar, and this post, hopefuly, will serve this purpose.

kick it on DotNetKicks.com

Some tips on events

19. November 2008
public class PluginService:IPluginService
{
    public event EventHandler<EventArgs> PluginStarted;
    public event EventHandler<EventArgs> PluginStarting;
    public void StartPlugin(int id)
    {
        PluginStarting(this, EventArgs.Empty);
        //Do some work
        PluginStarted(this, EventArgs.Empty);
    }
}

There is something obviously wrong with this code.

First of all, it is not doing the null check on the event. One should not assume that event will always have handlers.

There are 2 solutions to that issue:

  1. Dummy operation  
    public class PluginService:IPluginService
    {
        public event EventHandler<EventArgs> PluginStarted = delegate { };
        public event EventHandler<EventArgs> PluginStarting = delegate { };
        public void StartPlugin(int id)
        {
            PluginStarting(this, EventArgs.Empty);
            //Do some work
            PluginStarted(this, EventArgs.Empty);
        }
    }


    or some people prefer null object pattern but it is restricted to some specific delegate type.

    public class PluginService:IPluginService
    {
        public event EventHandler<EventArgs> PluginStarted = NullSubscriber.For<EventArgs>();
        public event EventHandler<EventArgs> PluginStarting = NullSubscriber.For<EventArgs>();
        public void StartPlugin(int id)
        {
            PluginStarting(this, EventArgs.Empty);
            //Do some work
            PluginStarted(this, EventArgs.Empty);
        }
    }

     

  2. Null Check
    First try would be to do the null check with a simple if:
    public class PluginService:IPluginService
    {
        public event EventHandler<EventArgs> PluginStarted;
        public event EventHandler<EventArgs> PluginStarting;
        public void StartPlugin(int id)
        {
            if (PluginStarting != null)
                PluginStarting(this, EventArgs.Empty);
            //Do some work
            if (PluginStarted!=null)
                PluginStarted(this, EventArgs.Empty);
        }
    }



    This wouldn’t work, since during the execution after the if is evaluated, the event handler may unsubscribe from the event, which will result in a null reference exception in the runtime(which is hard to catch in development)

    Another and the correct one try is:

    public class PluginService:IPluginService
    {
        public event EventHandler<EventArgs> PluginStarted;
        public event EventHandler<EventArgs> PluginStarting;
        public void StartPlugin(int id)
        {
            var handler = PluginStarting;
            if (handler != null)
                handler(this, EventArgs.Empty);
            //Do some work
            handler = PluginStarted;
            if (handler != null)
                handler(this, EventArgs.Empty);
        }
    }


    The key point here is not the null check, but how we do the null check. Since the events are immutable, we are now free to assign it. It won’t cause an issue when one of the subscribers unsubscribe.
    (thanks to Ayende for reminding us the Race condition)

    I think this is enough for the first post

    kick it on DotNetKicks.com

, ,