Boo trick: Even Nicer Hash Literals

time to read 2 min | 346 words

Boo has the concept of Has Literals, and it can really make a difference in a lot of cases. It makes some things possible to write. Even leaving aside common things like dictionaries constants, consider this signature:

public void Configure(IDictionary options)
{
	// do work
}

In Boo, I can call this method like this:

config.Configure({
	"connection_string": 	"data source...",
	"batch_size":		15
//	etc
})

This  is much clearer than the C# option, but we can do better.

public class UnknownHashLiteralKeyToStringLiteral : ProcessMethodBodiesWithDuckTyping
{
	public override void OnReferenceExpression(ReferenceExpression node)
	{
		IEntity entity = NameResolutionService.Resolve(node.Name);
		//search for the left side of a key in a hash literal expression
		if (node.ParentNode is ExpressionPair 
                && ((ExpressionPair) node.ParentNode).First == node
                && node.ParentNode.ParentNode is HashLiteralExpression)
		{
                	ExpressionPair parent = (ExpressionPair) node.ParentNode;
	                StringLiteralExpression literal = CodeBuilder.CreateStringLiteral(node.Name);
	                parent.First = literal;
	                parent.Replace(node, literal);
	                return;
        	}
		base.OnReferenceExpression(node); 
	}
}

Now, we have to register it in the compiler:

compiler.Parameters.Pipeline.Replace(
    typeof(ProcessMethodBodiesWithDuckTyping), 
    new UnknownHashLiteralKeyToStringLiteral());

Now, we can write this kind of code:

config.Configure({
	connection_string: 	"data source...",
	batch_size:		15
//	etc
})

It make the syntax much clearer, and it make quite a bit of a difference in the clarify of the code. I am going to put it into Brail, MonoRail has quite a few of methods that takes dictionaries, and it would make the syntax even nicer.