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);
    }
    

9 comments:

  1. I try the "unlimited int" and don't work... May be because I run the code in a browser....

    ReplyDelete
  2. Imho the Google developrs should had have a look at Io.
    http://iolanguage.com/

    This Darts just looks like a mixture from JavaScript, Tcl/Tk and a bit Java. I have feeled an immediate dislike about it. But I admit I'm biased.

    ReplyDelete
  3. Yes, I may have misunderstood the unlimited integers. It seems like they just overflow into floats when they get beyond a certain point. At least factorial(20) is an integer, but factorial(21) is a float.

    ReplyDelete
  4. A few comments:

    The arbitrary precision ints are not supported when compiled to JS for performance reasons -- they are represented using JS's Number type.

    Map doesn't require Hashable keys, though its default implementation HashMap does.

    In your for example, you have to declare the variable -- if you don't want to give a type you can use var. The web interface doesn't currently enable runtime type checks -- normally type errors are just warnings, but you can make them fatal compile errors (when compiling to JS) or generate runtime type checks with --enable_type_checks (for either the compiler or the VM).

    ReplyDelete
  5. I wonder if you just go a bit too far in your method of judging a language: every detail that differs from Smalltalk is bad :-) become:, really? that's pretty high on my list of ideas-of-old-languages-that-didn't-age-well.

    Hashable is good IMO. My experience with Java tells that the default Object.hashCode() is worthless and just asking for trouble. It conflates equality with identity by default, which is very rarely the intention. And it adds cost by requiring the VM to reserve some control bits in the header to store the system hashcode if it's ever produced (typically derived from its address - there's no other decent alternative), so the object can move around.

    ReplyDelete
  6. Hi Alan,

    I guess I still owe you a few answers.

    1. Resumable exceptions. No :-(. Efficient compilation to JS is a big goal with Dart. The reason the spec is the way it is motivated by the desire to avoid having to create the stack trace if it's not needed. If we only cared about the Dart VM, life would be easy.

    2. As John explained, the JS implementation doesn't always comply to the spec. Case in point: ints. Also noSuchMethod. In time, things will get better.

    3. Compiling Smalltalk to Dart would be fun - but it will be a while before you can do everything you like. You need the mirror system to materialize and mature, and you may find some things are restricted, especially in the browser. I'd start by targeting the VM, which is probably more spec-compliant right now.

    4. Tool support is ints infancy. The current Dart Editor is eclipse based. In general, remember this a very young system. Things will improve with time. We do know what is good and right :-)

    ReplyDelete
  7. Alan - I think that many of the mental cycles that went into the static typing system were spent at Animorphic on Strongtalk. When I was first exposed to the system in Newspeak, I had the same reaction as you. Then I realized how handy it was for revealing intention. [NB, some of the key contributors to Dart were responsible for Strongtalk and Newspeak]. If you want to see what Gilad is talking about with mirrors, I bet that reading up on Newspeak would help.

    ReplyDelete
  8. Thanks Gilad. I know you know, both individually and collectively :-)

    Now, if I can just get the Eclipse stuff to work properly...

    ReplyDelete
  9. I think isolates is probably the most important new contribution (well, not new to some, but could introduce a lot of people to a better model of concurrency). Optional typing is hard for me to get excited about, but I do see some value there...I'd probably be more inclined to use that if the tools let you press a button and make all the type annotations fade away. I find type annotations too noisy for general code reading, but handy when I really do want to know what the author intended a variable to reference.

    I'll be interested to see how well it's received...they're trying to move a lot of legacy stuff and entrenched interests. Part of me wonders whether it wouldn't make more sense to ditch the browser and start with a clean, secure language from scratch and just reinvent the browser along the way. It could be the true Web 2.0.

    ReplyDelete