Monday, October 10, 2011

Dart

Today is Thanksgiving in Canada, but the relatives were all over yesterday, so that gave me a lot of time to spend looking at Google's new "Dart" language, introduced this morning at the GOTO conference in Aarhus.

So here are my initial thoughts and questions, given that I've really only just read stuff and written a few code snippets. I'll try to keep it a little beyond just complaining that it isn't my favourite language :-) Overall, it's clearly very early days for it, and there are many things yet to be done, but it looks like it does a lot of things right and has some serious potential.

Open Questions

  • What sort of tool support is there? I've seen that talked about, but not being at the keynote I haven't seen it demoed yet.
  • How exactly does the exception model work? One of the things I find most useful in Smalltalk is that exception handling is done in two phases. First, we find the handler and run it, and only after that do we unwind the stack. That means that when developing, an unhandled exception can put us right into the debugger at the point of the exception and with the ability to see the code and modify it. There are hints in the spec that suggest Dart is able to do this. The exception handler definitely gets a strong representation of the stack which "becomes undefined" after it's finished. I'd like to know more. Exceptions seem to be able to be any object, though many of the exceptions are classes. That seems like it might run into problems when you start wanting to be able to consistently ask certain things of an exception, but maybe the things you want to ask aren't really the exception object but the other things that come along into the handler.
  • Can I do some equivalent of block return? So, for example, the Dart collection library includes some basic iteration methods. There's a forEach, and there's a filter (think #select:) but there isn't a detect:. How would I write an equivalent of detect: in terms of a provided forEach method, since the return from a function just returns from the inner block. Maybe I could do it with an exception, but that seems awfully ugly. Or I could save the value and let it just keep going through the rest of the collection, but I don't want to do that. And that leads into...
  • Can I add my own control structures? And if so, how pleasant will they be to use? This has a few pieces. Can I extend existing classes? Javascript lets me do this easily, as does Smalltalk. Newspeak doesn't, on philosophical grounds. But to me this seems awfully useful for being able to define my own control structures and other language elements, and that's an important piece of being able to extend the language into its own DSL.
  • In general, I find myself thinking about typical Smalltalk tools and wondering how doable it would be to write them in Dart. Maybe I'll give it a try and find out.

Things I Like

  • Everything's an object. No primitive types and no mismatched operations because of it.
  • Most things are message sends. There's still too much syntax for my taste, but most of the important stuff goes through message sends.
  • Unlimited size integers
  • There's a doesNotUnderstand: equivalent (noSuchMessage)
  • There's a fairly significant type system. You can completely ignore it.
  • The setters and properties are nice. You can reference things as properties, and they go through the get/set methods if you've written them.
  • Also, there's operator overloading, but in the sense that operators are really just methods, and it lets you write some nice things like
  • things.stuff[1]="Foo"
  • Types like "int" are actually interfaces. Though some people were arguing that it's confusing to have them as lowercase.
  • A late addition - no separate compile step.

Things I'm Not Quite Sure About

  • The concurrency model with single-threading, but the ability to spawn actor-style isolates sounds quite interesting. That'll be interesting to see.
  • The default return value is null, not self. This is philosophically because if you don't explicitly return something and you try to make use of the return value it's probably a mistake and you want it to fail fast. But I'm not sure this wouldn't lead to a lot of extra statements in methods if you do tend to make use of the return values.
  • There's an interpolated string form that they seem to favour, where you can embed ${expression} into a string. But one comment that I read argued that this wasn't as useful as being able to put in things more like positional arguments and then bind that to a set of values, and I think they have a point.
  • Reflection is still a to-do list item.
  • The syntax for functions is pretty lightweight. In the simplest case, something like (excuse my formatting)
     () => 3;
or
     (aNumber) => aNumber + 1;
and the more complex cases where it's not a single expression in the body are
     (aNumber) { print(aNumber); return aNumber + 1;};
That's nicely short. I find the parentheses to be a bit of syntactic noise that bothers me more than the very simple [3], but I might be able to live with it.


Things I Could Wish For
  • There's no become:, but then I wouldn't really have expected to see one. And I'd have rather had keyword argument syntax, but I didn't really expect that either.
  • Classes aren't objects. There are "static" methods but they aren't really class methods, and you can't have an expression that evaluates to a class. They argue that the class/instance method distinction has been shown to be confusing for users. There is a fairly sophisticated mechanism for constructors which might be enough for the most common uses of class methods, it's not clear.
  • The reserved words seem a bit more intrusive than they need to be. Or maybe it's just that I got bitten trying to write a method named "do" :-)
  • It seems like only certain things are Hashable and thus eligible as Map keys. That seems restrictive. But I might just be confused about that one.
  • There's a lot of spec space and presumably a lot of mental cycles spent on the static typing system. I'd just as soon that energy went on more worthwhile things :-)  Mostly you can ignore it, but I did run across one interesting case. There's a for loop construct that will let you loop over a collection. It requires you to put in a type, but ignores it. So I can't leave out the "int" in
  • main() {
      var a = [1,2,3];
      for(int x in a) print(x);
    }
    
    but I can put in nonsense and it still runs
    main() {
      var a = [1,2,3];
      for(Exception x in a) print(x);
    }