2011-10-10

Google Dart – overview and comments

Today, it has finally happened: At the GOTO conference, Google has officially presented its new programming language, Dart. This post gives an overview of Dart and provides a few comments on how it fits into the current programming language landscape.

Information on Dart

This post is based on the following sources on Dart:

Dart in a nutshell

  • Currently, Dart is not a JavaScript replacement, but rather a “better Java” plus a next-generation GWT.
  • The language is less like JavaScript and more like an improved version of Java: reified generics, first-class functions, optional types (no type errors, just warnings), getters and setters, no primitive types.
  • It is still part of the HTML5 world and includes a DOM library.
  • There is IDE support, via an Eclipse plug-in.

An overview of the language

Functions

    // named function
    void sayGreeting(String salutation, String name) {
      final greeting = '$salutation $name';
      print(greeting);
    }
    
    // function with statement body
    window.on.click.add((event) {
      print('You clicked the window.');
    })
    
    // function with expression body
    var items = [1, 2, 3, 4, 5];
    var odd = items.filter((i) => i % 2 == 1);
    print(odd); // [1, 3, 5]

Classes

    class Point {
      Point(this.x, this.y);
      distanceTo(Point other) {
        var dx = x - other.x;
        var dy = y - other.y;
        return Math.sqrt(dx * dx + dy * dy);
      }
      var x, y;
    }
Class members:
  • Methods: see distanceTo(), above
  • Operators
        operator +(other) => new Point(x+other.x, y+other.y);
    
  • Fields
        num left, top, width, height;
    
  • Getters, setters
        num get right()           => left + width;
            set right(num value)  => left = value - width;
    
  • Constructors
    • Normal constructors
          Rectangle(this.left, this.top, this.width, this.height);
      
      Prefixing this. to parameters means that they will be automatically assigned to fields. This has been one of the proposed feature for JavaScript class literals.
    • Named constructors. Without overloading, you need a way to distinguish between alternate constructors.
          Point.zero() : x = 0, y = 0;
      
    • Factory constructors are a way to mark constructors so that no instance is produced automatically. Then you can return cached instances or instances of a subclasses.
            factory Symbol(String name) {
              if (_cache.containsKey(name)) {
                return _cache[name];
              } else {
                const symbol = new Symbol._internal(name);
                _cache[name] = symbol;
                return symbol;
              }
            }
      
            Symbol._internal(this.name);
      

Interfaces

    interface Shape {
      num perimeter();
    }
    class Rectangle implements Shape {
      final num height, width; 
      Rectangle(num this.height, num this.width); 
      num perimeter() => 2*height + 2*width;
    }

Factory classes for interfaces. An interface can specify a factory class which can be considered its default implementation. You can now directly instantiate the interface, its constructors delegate to the constructors of the factory class. If you use normal constructors then that is not much different from a normal class (but you don’t get the multiple inheritance of interfaces). Things become interesting with factory constructors, because you can create your own instance (including an instance of a subclass). I’ve seen interfaces being abused in Java code, to the point where there wasn’t a single class that didn’t implement an interface, so we’ll see where this goes. This feature does not provide mixin functionality. That is, if you implement an interface, you don’t get default method implementations via the factory class.

Isolates

Erlang-style concurrency:
    // Receive messages
    class Printer extends Isolate {
      main() {
        port.receive((message, replyTo) {
          if (message == null) port.close();
          else print(message);
        });
      }
    }

    // Send messages
    main() {
      new Printer().spawn().then((port) {
        for (var message in ['Hello', 'from', 'other', 'isolate']) {
          port.send(message);  
        }
        port.send(null);
      });
    }
Quoting the language specification:
Dart code is always single threaded. There is no shared-state concurrency in Dart. Concurrency is supported via actor-like entities called isolates. An isolate is a unit of concurrency. It has its own memory and its own thread of control. Isolates communicate by message passing. No state is ever shared between isolates. Isolates are created by spawning.

Generics

Reified generics (parameterized types):
    main() {
      print(new List<String>() is List<Object>);
      print(new List<Object>() is List<String>);
      print(new List<String>() is List<int>);
      print(new List<String>() is List);
      print(new List() is List<String>);
    }

Strings

  • Triple quotes for multi-line strings
        var message = """
        Dear $user!
    
        There has been a problem!
        """;
    
  • $ for variable interpolation:
        var foo = "world";
        print("Hello $foo");
    
  • ${} for expression interpolation:
        print("Result: ${x + y}");
    

Miscellaneous features

A few interesting tidbits:
  • There is a standard library with collection classes (List, Set, Queue, Map, etc.) and a DOM API.
  • Equality is handled via the == operator and delegates to the Comparable interface (for non-null values).
  • You cannot access JavaScript directly from Dart. In the future, there might be a way to run JavaScript code in an isolate and communicate with it via message passing. In GWT, integrating native JavaScript is easy. Whether that ease will ever come to Dart will depend on how Google eventually positions it – as a JavaScript replacement or as a Java/GWT replacement.

Running Dart

There are several ways of running Dart code. Quoting the Technical Overview:
  • Translate Dart code to JavaScript that can run in any modern browser: Chrome, Safari 5+, and Firefox 4+ (more browser support coming shortly).
  • Execute Dart code directly in a VM on the server side.
  • Use Dartboard to write, modify, and execute small Dart programs within any browser window.

Dart is not finished yet

Upcoming features:
  • Enums
  • Possibly: a reflection API
  • Possibly: pattern matching (think: a more powerful switch for objects). Useful for isolates to better handle messages.
  • “The Dart VM is not currently integrated in Chrome but we plan to explore this option.” [source: Google Code blog]

More information on the web

Features and details

@dalmaer:
66 folks listed as owners/commiters for Dart. Holy large team! http://code.google.com/p/dart/people/list
@pmuellr:
Looks like Dart allows typedefs for functions, which should be nice for defining callback signatures.

Tongue in cheek

@mrspeaker:
I'll give it this, Dart certainly solves the problem of JavaScript not having anything to do with Java.
@jordansissel, in a similar vein:
Dart: Putting the Java back in JavaScript.
@jashkenas:
My favorite Dart compiler class: Hack.java
@maccman:
Dart's source contains this little gem:
static bool isVm() { return 1234567890123456789 % 2 > 0; }

How does Dart fit into the current programming language landscape?

Freely paraphrasing a tweet by @pilif:
  • If you like Java and can’t get yourself to like JavaScript, you program Dart.
  • If you like Ruby and can’t get yourself to like JavaScript, you program CoffeeScript.
  • If you like JavaScript, you program JavaScript.
What do you get compared to Java?
  • Currently, Dart is almost like GWT (which is not a bad thing): Running “natively” on a virtual machine on the server, compiled to JavaScript on the client.
  • Basing the Dart IDE on Eclipse makes sense, because you get a lot of functionality (such as Git support) for free and because it is familiar to Java programmers.
  • Dart seems like an upgrade of Java, like a cleaned up version. It even carries over some negative Java-isms, such as fields automatically becoming part of the local scope.
What do you get compared to JavaScript?
  • Main Dart killer features: optional types, actor-like concurrency via isolates. However, you can do a lot via type inference in JavaScript, class literals will come to ECMAScript.next [2] and web workers are becoming more sophisticated all the time. Dart foregoes some of JavaScript’s quirks, but then again, so does ECMAScript.next.
  • In many ways, Dart feels less versatile than JavaScript. For example, JavaScript object literals are a very powerful feature. Dart is more static and only has classes.
  • Dart seems to have decent tooling, but it’s based on Eclipse. In contrast, many JavaScript IDEs that are currently in development are based on web technologies. Writing an IDE for a language in the language itself has many advantages.
  • At the moment, Dart isn’t even faster than JavaScript on V8. Presumably, that will change in the future. But this goes to show how fast JavaScript has become and that it didn’t need static types to get there.
  • Not a JavaScript replacement? Quote from the talk:
    We are not targeting JavaScript, but rather fragmented mobile platforms.
    I’m not sure what that means. Will Dart target these platforms by compiling to JavaScript or by compiling to the native mobile environments? It almost makes you wonder whether Google really knows what to do with Dart.
  • Google could have gotten the same results by supporting ECMAScript.next [2] (plus possibly some advanced, not yet standardized features) and Traceur [3].
As things are now, we have a clean but fairly simple language without any stand-out features. For example, not even multiple inheritance via something like traits is supported. Dart’s syntax is of the familiar but generic C-style variety (Java, JavaScript, C#). As long as Chrome does not come with a built-in Dart VM, Dart feels more like a Java replacement and a next-generation GWT. Maybe it should stay that way and Google should use native Dart on servers and Android (to avoid copyright troubles) and continue to always compile it to JavaScript on web browsers. That would prevent an unpleasant fragmentation in client-side native languages.

Tentative pointers in that direction are Google not yet committing to integrating the Dart VM into Chrome and saying that Dart doesn’t target JavaScript, but a “fragmented mobile platform”. That is a marked change in tone from the openly anti-JavaScript document that was published last year [1]. And it is also a very weak message about what Dart actually is. Google will have to eventually give clear answers. By missing the opportunity to do so during today’s event, they have weakened the impact of the launch.

If you want to see a truly innovative language, take a look at Newspeak: Its elegant syntax has the well-known Smalltalk advantages and there are fresh new ideas regarding modularity and IDEs (check out the paper on Hopscotch). Gilad Bracha, one of its creators, is part of the Dart team, which is why I expected more from that language.

Related reading

  1. Google Dart to “ultimately ... replace JavaScript” [the prelude to the GOTO Dart presentation]
  2. ECMAScript.next: the “TXJS” update by Eich
  3. Google’s Traceur: compile ECMAScript.next to JavaScript on the fly

14 comments:

person287 said...

It's called DART, and Google Europe is located around DART (Dublin Area Rapid Transport System). Waaay too easy to get confused!!!

Alexander Gallego said...

Honestly after following this blog for 1 month, I have learned more about google than any other blog around. Thanks. Great source of info.

I wrote a couple of dart 'hello-world' programs. Seems cool. Probably going to wait for some google magic to translate my gwt (java based) to some dart equivalent for the client side.

Axel Rauschmayer said...

I’m glad to hear it! It’ll be interesting to see how Google eventually positions Dart. I think it would work well as a Java/GWT replacement.

chrissullins said...

Object literals can be done via maps, which can contain anything a javascript object literal can contain. JSON seems to be valid syntax. You can, of course, add functions to your maps, so as long as you don't mind accessing members via square bracket syntax (which is admittedly far less terse).


var abc = {"a": [true, false, null], "b": (){return 5;}, "c": 5.6};

Axel Rauschmayer said...

Using an object as a map is actually (slightly) abusing it (but you have no choice). So JavaScript needs true maps.

On the other hand, creating objects without classes is a major feature of JavaScript and increases its versatility.

It does look like you can use maps like objects in Dart, though. Does "this" work?

chrissullins said...

Good catch! I should have thought of that use case.


`this` doesn't seem to be a dynamic principle. It's might just be assigned by the compiler to be whatever object it knows the function is in. When you pass a member function of an object around as a variable, it remains attached to that object -- there's no such thing as `call` or `apply`. Whenever I try to reference `this` in a function, I get a compile-time error "Cannot use 'this' in a top-level method". This occurs whether it's an anonymous function or not.

Another thing I'm worried about is feature detection: there doesn't seem to be a mechanism to say "Does this object have this function?" except using try-catch. That kinda undermines the whole javascript replacement goal.

Det said...

"One can
instantiate an interface, but actually instantiates the factory class
behind the scenes. The constructors of an interface delegate to the
constructors of the factory class. I’m not sure how that is any
different from an abstract class."

This is because you are plainly wrong about that. The constructor of that interface delegates to the factory "constructor", i.e. a static factory method in the factory class.
But the factory class is a factory implementation and doesn't even have to implement the interface itsself. Instead it can instanciate any other class that implements the interface.  Factory pattern indeed.
But the abstract class notion does not fit in any way.

Example:



interface Greeting factory Creator {


   show();


   Greeting();


}


 


class Creator {


   static var cond
= false;


   factory
Greeting() {


        return
cond? new World() : new Mundo();


   }


}


 


class World implements Greeting  {


   show() { print(
"Hello World" ); }


}


 


class Mundo implements Greeting  {


   show() { print(
"Hola Mundo" ); }


}


 


 


main() {


   Creator.cond =
true;


   new
Greeting().show();


}

Det said...

Damn ... what did this page do with the format ?!?

Axel Rauschmayer said...

Good point. I’ve updated the post accordingly.

Ivan Lazarte said...

Hm, I really like Java and program CoffeeScript.  Uh oh!

Honestly, it comes down to this: Javascript is the worlds greatest language, until it comes time to work in Javascript.  When we can refactor a 10K, hm, 2K, how about even 50 line Javascript program in about 30 seconds without worrying about references, then people will stop trying to reinvent Javascript as something else.

Until then, I'm open to anything that alleviates the Javascript problem, which currently for me is CoffeeScript (honestly though I'll try Dart this weekend probably)

Axel Rauschmayer said...

You can edit existing posts. pre tags work.

Axel Rauschmayer said...

Tools are indeed JavaScript’s current weak spot and one reason why GWT is still a compelling solution for web programming.
Apart from better support for inheritance, what is it that CoffeeScript gives you that you miss from JavaScript?

Brianoh said...

Google - thank you, thank you, thank you. Please expedite the development of Dart! Goodbye Javascript - you did not evolve as needed.

Axel Rauschmayer said...

Note that Dart is still work in progress and that ECMAScript.next is coming along nicely and will fix most of JavaScript’s bad parts. If you don’t like JavaScript now, chances are you never will. Then Dart is probably a good solution for you. But the statement “you [JavaScript] did not evolve as needed” ignores the progress that is made with ECMAScript.next.

Web Analytics