Sunday, October 16, 2011

Dart keyword arguments

Coming from a Smalltalk background, one of the things I like in it is the message format, with keywords with colons separating the arguments rather than mathematical function syntax. So, e.g.
    aDictionary at: 12 ifAbsent: ['default'].

Dart has operators you can define as messsages, so their default syntax would be

But that's not the same operation, as it doesn't have the ability to say what to do if the key is missing. It does define

but that's not the same as at:ifAbsent:, both because it always adds something to the map/dictionary, and because the thing you're adding is a value, not the result of evaluating a block.
However, Dart also has named keyword arguments to methods. They're not shown, as far as I saw, in the introductory materials on the site, and I didn't notice them in the sample code that I looked at, but they're in the spec. The form is
   at(var key, [ifAbsent]) {
     if (containsKey(key)) return this[key];
     if (ifAbsent is Function) 
        return ifAbsent(); 
        return ifAbsent;

and to invoke it we'd do something like
  Map aMap = { "one": 1, "two":2};"one",ifAbsent: "default");

or, if we felt like formatting it slightly differently, it seems that there can be whitespace between the dot and the method, so
     ifAbsent: "default"
     at: 'one',
     ifAbsent: ()=> throw SomeException;

Both of those latter forms, while they have some additional bits of punctuation, look interestingly like syntax I'm more used to. Named parameters can also have default values, which could also be useful, though I tried
  someFunction(var a, [b= (var x)=>x * 2])
and while it didn't complain of a syntax error, variable b was null if not specified. That might just be a compiler bug, or it may be that a closure literal isn't allowed there, I'm not sure.
I haven't tried using these on any kind of scale to see how usable they would be in practice, and they obviously aren't the preferred style in the examples, but I found it interesting. And as a minor point, it's odd that for normal parameters I have to specify either a type or "var" but that doesn't seem to be necessary for the named parameters.