Sergio and the sigil

Language Envy - hash literals

Posted by Sergio on 2009-01-05
Language Envy: This post is part of a series where I wish C# had a particular feature I came to like when working with other programming languages.

It's easy to let a small language feature go unnoticed. The more I spend time writing JavaScript and Ruby, the more one little detail shows itself loud and clear when I go back to my trusty C# (well, it shows itself by not being absent, if that makes any sense.)

The little language detail I'm writing about today is the literal syntax for hashes. Especially in JavaScript, because all objects are just hashes on steroids, which makes the literal object syntax become one and the same with the hash literals.

In JavaScript it's easy as 1-2-3. It's not surprising so many libraries are adopting hash parameters.

//Prototype.js sample
var elements = { success: 'myDiv', failure: 'errorDiv' };
var ajax = new Ajax.Updater(
	elements, 
	'getData.aspx', 
	{ method: 'get', onFailure: reportError }
	);
//jQuery sample (jQuery UI)
$('#fromDate').datepicker({rangeSelect: true, firstDay: 1});
$("#search").autocomplete("/product/find",
	{ autoFill: true, delay: 10, minChars: 3 }
	);

Now, I understand that part of the popularity of hashes in JavaScript and Ruby is due to the loose typing of these languages. But if the syntax wasn't light, APIs like the above ones would be much more painful to use.

C# 3 does have a hash syntax (or, more accurately, a dictionary one.) Unfortunately, dictionary initializers, although being a step forward, still leave noise to be removed.

// hypothetical search API 
var books = FindWithCriteria<Product>(
              new Dictionary<string,object>
              {
                {"Category", Category.Books},
                {"MinPrice", 33.45},
                {"MaxPrice", 50.00},
                {"Contains", "asp.net"}
              });

Hmmm, no, thanks. Maybe that's the reason we are starting to see some APIs that use (abuse?) anonymous objects and reflection to create hashes.

// hypothetical search API 
var books = FindWithCriteria<Product>(
              new { 
                Category = Category.Books,  
                MinPrice = 33.45,
                MaxPrice = 50.00, 
                Contains = "asp.net" 
              });

This last one doesn't look so bad on the surface, but we know what is going on under the covers so it's like putting lipstick on a pig. If, instead of using reflection at run-time, the compiler had support for converting the above anonymous object into a IDictionary<string,object>, then we would have a more convenient and efficient way of creating hashes. Maybe it's too late to introduce a feature like that while maintaining backwards compatibility.

I believe when you add a language feature that is elegantly designed (i.e. clean and unnoticeable,) it becomes popular more quickly — just like what is happening with lambdas . The existing alternatives for creating hashes in C# 3 are still too noisy or inefficient to be integrated in our code without reducing the readability or incurring a performance penalty.