Dart programming language - Introduction

This is the third of a post series where I’m going to talk about some new programming languages with a nice future ahead. During this series I’ll explore deeper the Ceylon, Dart, Elixir, Rust and Swift 2 languages.

The plan is to make a post a week until December 15 (or maybe a little more) and spend 2 weeks exploring each one of them. In the first week I’ll explore the general aspects of the language and make some comparisons with other very known and established languages. In the post of the second week I’ll go deeper inside each one of the languages and explore the individual advantages on use them.

All the posts

  1. Ceylon Introduction
  2. Ceylon Usage
  3. Dart Introduction
  4. Dart Usage
  5. Elixir Introduction
  6. Elixir Usage
  7. Rust Introduction
  8. Rust Usage

Preface

There are hundred of programming languages out there. Which one should we use? Which help do we have to choose well? How do they compare to each other? This document is an attempt to provide some answers to these questions. Naturally, it would not be possible to provide complete answers: as I mentioned, there are too many programming languages. Nevertheless, we chose five languages with a potential to grow in importance in the coming years. These programming languages are Elixir, Rust, Dart, Swift and Ceylon. During this project, we shall be talking about each one of them. These discussions will be in breath, not in depth. Their goal is to provide the reader with the minimum of information necessary to compare them, and who knows, to lure one or other interested person in learning them in a greater level of details. In any case, we hope to contribute a bit to the popularization of these programming languages, which - likely - will be paramount to the development of computer science in the next ten years.

Dart

How did it appear?

Dart is an open source script language focused in web applications and developed by Google1. It was announced at GOTO Conference 2011 (Aarhus, Denmark)2 and its first stable release, Dart 1.0, comes in November 20133.

It was designed by Lars Bak and Kasper Lund, both of them employed by Google. Lars has contributed to the Chrome Browser project developing the V8 JavaScript Engine4, the open source JavaScript engine that runs Google’s browser and gave birth to some other big projects like Node.js5.

Why was it designed and implemented?

In the words of Google6:

At Google we’ve written our share of web apps, and we’ve tried in many ways to make improvements to that development process, short of introducing a new language. Now we think it’s time to take that leap. We designed Dart to be easy to write development tools for, well-suited to modern app development, and capable of high-performance implementations.

But in pragmatic terms all this means that Google thinks that JavaScript is unproductive and his proposal to improve it was to design a better language for the browsers. Google is investing a lot of effort on both sides, JavaScript and Dart7 and believes that developers should have a choice when they build for the web. Adding a new option, such as Dart, does not imply replacing the JavaScript already existing option8.

Dart has its own Virtual Machine which enable the Dart programs to run on every systems. There is also a dar2js compiler which makes Dart code compile to JavaScript code and run on modern browsers. And there is the third option, the Dartium9 project that brings the Dart VM inside a Chromium Browser, so Dart can be used directly as a browser’s script language like JavaScript does at Chrome nowadays.

The Dart team isn’t focused in bring Dart to Google Chrome but in compiling Dart to JavaScript. They have decided not to integrate the Dart VM into Chrome but to generate a better JavaScript compilation10 11.

How can we use it, e.g., install and run?

Dart has it’s own Virtual Machine and has easy installations on all major systems. The current stable version of Dart is 1.12.2. For installation on a Mac you can use Homebrew:

brew tap dart-lang/dart
brew install dart

Also you can install the Dartium browser with:

brew tap dart-lang/dart
brew install dart --with-content-shell --with-dartium

For Linux there are Debian packages and these are the commands for installation on the Debian based systems:

sudo apt-get install apt-transport-https
sudo sh -c 'curl https://dl-ssl.google.com/linux/linux_signing_key.pub | apt-key add -'
sudo sh -c 'curl https://storage.googleapis.com/download.dartlang.org/linux/debian/dart_stable.list > /etc/apt/sources.list.d/dart_stable.list'
sudo apt-get update
sudo apt-get install dart

There are other options to build and install on various Linux distros12.

There is also the versions of the SDK where you can download the portable package and link to your system’s path whatever you want: https://www.dartlang.org/downloads/archive/.

Now let’s check if the installation works. In any path (Dart doesn’t force directory structure) create the file called hello.dart with the following content:

main() {
  print("Hello Dart!");
}

Run with dart hello.dart and the “Hello Dart!” message must show up. Now test the JavaScript compilation by running, with the same hello.dart file, the command:

dart2js hello.dart

You might have the message Dart file (hello.dart) compiled to JavaScript: out.js. The contents of the file out.js is huge if compared to the initial Dart code. We will have more details of JavaScript compilation in the future. Now,if you have a JavaScript runtime in your system, like Node.js, you will have the same result of running the hello.dart file if you run:

node out.js

If you don’t have a JavaScript runtime in your system, you’ll test the JavaScript compilation by creating a test.html file in the same directory of the out.js file with the following content:

<script type="text/javascript" src="out.js"></script>

Then open the file in a modern browser (like Google Chrome or Mozilla Firefox) and open the browser console (by pressing the F12 key) and the message Hello Dart! is printed in the browser’s console.

Simple programs

I will demonstrate some features of the language by writing some simple programs and analysing some points right after it.

Dart Packages

Every Dart program is a library, even if it the program is not written using libraries definitions. Libraries not only provide APIs, but are a unit of privacy: identifiers that start with an underscore (_) are visible only inside the library (like private or protected members in Java).

Libraries can be distributed using packages. Dart has a powerful package manager that resolve package dependencies and package installation as we specify our project dependencies. Dart has also a huge repository of packages[https://pub.dartlang.org/] that delivers the packages listed as project’s dependencies.

Let’s implement a Dart example program that uses the package manager to install a library. This is the code of the program request.dart:

import 'dart:math';
import 'package:http/http.dart' as http;

readFromRemoteFile(url, sentence) {
  var rng = new Random();
  print(sentence);
  http.get(url).then((val){
    var texto = val.body;
    var frases = texto.split("\n");
    print(frases[rng.nextInt(frases.length)]);
  });
}

ramones() {
  readFromRemoteFile('http://aurelio.net/doc/ramones.txt',
    "Please wait, consulting the Ramones:");
}

main() {
  ramones();
}

The program above makes a http get request13 to a document with some phrases (one per line), choose a random line and print the phrase on it. If we try to run this program now, we’ll have some errors:

$ dart _request.dart
Unhandled exception:
Could not resolve a package location for base at file:///home/taiar/dev/monografia/mono1/dart/get_request/get_request.dart
#0      _handlePackagesReply (dart:_builtin:416)
#1      _RawReceivePortImpl._handleMessage (dart:isolate-patch/isolate_patch.dart:148)

As the error is telling us, the program could not resolve the package location. That happens because the command import 'package:http/http.dart' as http; is trying to use a package that is not from Dart’s default SDK and is not present in our environment. Dart SDK ships with a program called pub. With this tool we can define our program’s dependencies and install all the possible package’s dependencies these packages need to work. To configure the project’s dependencies, we’ll have to use the pub specifications. We define the program’s dependencies with a file called pubspec.yaml in the root of our project. For this example, the pubspec.yaml should look like this:

name: request
dependencies:
  http: any

It says that, for our project called request, we have a dependency with the package http, at any version (we are assuming that all http package versions have the functionalities we need to run our program). To install the dependencies, we have to run the command:

$ pub get
Resolving dependencies... (5.5s)
+ charcode 1.1.0
+ collection 1.1.3
+ convert 1.0.0
+ crypto 0.9.1
+ http 0.11.3+2
+ http_parser 1.1.0
+ path 1.3.6
+ source_span 1.2.1
+ stack_trace 1.4.2
+ string_scanner 0.1.4
+ typed_data 1.0.0
Changed 11 dependencies!

As you can see, it downloads lots of other packages, all they are dependencies for the http package (and, or course, for our program). All done, if we try to run the program again, it might work correctly:

$ dart get_request.dart
Please wait, consulting the Ramones:
& I won't be back till monday

Asynchronous Programming

Dart is a single-threaded programming language. If any code blocks the thread of execution (for example, by waiting for a time-consuming operation like some heavy I/O operation or a network request) the program effectively freezes. Asynchronous operations let your program run without getting blocked. Dart uses Future objects to represent asynchronous operations.

Lets make a new version of our previous request.dart program. This new version will make 2 HTTP Get request: the usual Ramones quotes and the other one teach us how to say “Merry Christmas” in various languages of the world. This is the code:

import 'dart:math';
import 'package:http/http.dart' as http;

readFromRemoteFile(url, sentence) {
  var rng = new Random();
  print(sentence);
  http.get(url).then((val){
    var texto = val.body;
    var frases = texto.split("\n");
    print(frases[rng.nextInt(frases.length)]);
  });
}

ramones() {
  readFromRemoteFile("http://aurelio.net/doc/ramones.txt",
    "Please wait, consulting the Ramones:");
}

natal() {
  readFromRemoteFile("http://www.crossladies.com/feliz_natal.txt",
    "This is how we say 'Merry Christmas' in:");
}

main() {
  ramones();
  natal();
}

Running the program, we would have a result like:

Please wait, consulting the Ramones:
This is how we say 'Merry Christmas' in:
Havaiano  Mele Kalikimaka
Come along (surfin') baby wait and see (surfin' safari)

There is one problem with the program. The program has race conditions. When the ramones function is called, it prints a message on the screen and make the HTTP get request, setting a callback function that choose the line and prints the message when the response of the request returns. Before the response returns, the natal function is called, printing the message and waiting for another response from HTTP. Then the two responses are back (on diferent times) and printed too.

Dart has the concept of Future. A Future represents a means for getting a value sometime in the future 14 15 16. When a function that returns a Future is invoked, two things happen:

  1. The function queues up work to be done and returns an uncompleted Future object.
  2. Later, when a value is available, the Future object completes with that value (or with an error; we’ll discuss that later).

Lets rewrite the program solving the race conditions with futures to see how it works:

import 'dart:math';
import 'package:http/http.dart' as http;

readFromRemoteFile(url, sentence) async {
  var rng = new Random();
  print(sentence);
  var response = await http.get(url);
  var texto = response.body;
  var frases = texto.split("\n");
  print(frases[rng.nextInt(frases.length)]);
}

ramones() async {
  await readFromRemoteFile("http://aurelio.net/doc/ramones.txt",
    "Please wait, consulting the Ramones:");
}

natal() async {
  await readFromRemoteFile("http://www.crossladies.com/feliz_natal.txt",
    "This is how we say 'Merry Christmas' in:");
}

main() async {
  await ramones();
  natal();
}

We have all those asynchronous methods. We mark’em as asynchronous. We tell the program, which methods it must await the result for continue the execution. That’s all!

Quotes

References

comments powered by Disqus