« January 2009 | Main | March 2009 »

February 22, 2009

Scala for C# programmers, part 4: multiple return values

Everybody hates out parameters.  We all know that code like this just isn't nice:

Widget widget;
if (widgetDictionary.TryGetValue(widgetKey, out widget))
{
  widget.ReticulateSplines();
}

And once you start composing higher-level functions into the mix, it gets positively nasty.  Suppose I want to make a HTTP request.  Well, that's going to produce two outputs in itself, the success code and the response data.  But now suppose I want to time it.  Writing the timing code isn't a problem, but now I have three outputs, and to paraphrase Was Not Was, I feel worse than Jamie Zawinski.

You can get around this in specific situations by creating custom types like DictionaryLookupResult or TimedHttpRequestResult, but eventually the terrible allure wears off, and you just want it to work.

Enter tuples.  A tuple is just a small number of values -- a single value, a pair of values, a triplet of values, that sort of thing.  You can tell that tuples were named by mathematicians because the name only makes sense when you look at the cases you hardly ever use (quadruple, quintuple, sextuple, etc.).  If C# had tuples, our timed HTTP request might look a bit better:

public Tuple<bool, Stream, TimeSpan> Time(Func<Tuple<bool, Stream>> action)
{
  StartTimer();
  var result = action();
  TimeSpan howLong = StopTimer();
  return new Tuple<bool, Stream, TimeSpan>(result.First, result.Second, howLong);
}

var result = Time(() => MakeRequest(uri));
var succeeded = result.First;
var response = result.Second;
var howLong = result.Third.
Console.WriteLine("it took " + howLong);

What's that you say?  Not better?

The reason this keeps getting verbose on us is that C# doesn’t provide any syntatical support for tuples.  To C#, a Tuple<> is just another generic type.  To us, the readers, a Tuple<> is just another generic type with particularly unhelpful member names.

Really, what we're really trying to articulate by returning a Tuple<> is, "this method has several outputs."  So what do we want to do with those outputs?  We want to access them, for example to stash them in variables, without having to construct and pick apart the tuple one value at a time.  That means the language has to provide some kind of syntax-level support for tuples, instead of treating them like every other class the compiler doesn’t know about.

Many functional languages have exactly this kind of syntactical support, and Scala is no exception.  Here’s how the above pseudo-C# looks in Scala:

def time(action: => (Boolean, Stream)): (Boolean, Stream, TimeSpan) = {
  startTimer()
  val (succeeded, response) = action
  (succeeded, response, stopTimer());
}

val (succeeded, response, timeTaken) = time(makeRequest);
Console.WriteLine("it took " + timeTaken);

Notice the multiple variables on the left hand side of the time call?  Notice the (Boolean, Stream, TimeSpan) return type of the time method?  That return value is effectively a tuple type, but instead of having to capture the returned tuple in a Tuple<> variable and extract its various bits by hand, we are getting the Scala compiler to (in the time function) compose the tuple implicitly for us, without us having to write the constructor call, and (in the calling code) unpick the tuple into meaningful, named variables for us without us having to explicitly copy the values one by one and by name.

(By the way, a proper implementation of the time() method wouldn’t be restricted to (Boolean, Stream) results: we’d be looking to write a method that could time anything.  I’ve skipped that because I don’t know how to do it it would distract from the point at hand.)

How would this play with the dictionary example?

val (found, widget) = widgetDictionary.GetValue(key)
if (found) {
  widget.ReticulateSplines()
}

We don’t actually save any lines of code, what with having to now capture the “found” value into a variable and test it separately; and it’s not as if the original C# version was horribly unreadable anyway.  So maybe this is a matter of taste, but I find this a lot easier to read and to write: all the outputs are on the left of the equals sign where they belong, instead of being spread between the assignment result and the parameter list, and we don’t have that odd Widget declaration at the top.

Encouragingly enough, .NET 4.0 will include a Tuple class, I believe precisely in order to support functional and other languages that use the multiple return value idiom.  Unfortunately, C# 4.0 still isn’t getting syntactical support for them, so we’re stuck with out parameters or special result types for now.

February 22, 2009 in Software | Permalink | Comments (7) | TrackBack