Sample Code

Send feedback

This collection is not exhaustive—it’s just a brief introduction to the language for people who like to learn by example. You may also want to check out the following pages.

Language Tour

Higher text-to-code ratio than here.

Cookbook

A set of concrete recipes to get you started with common programming tasks.

Hello World

First things first:

void main() {
  print('Hello, World!');
}

Variables

We’re not explicitly typing the variables here. We could, but type inference works for us.

var name = 'Voyager I';
var year = 1977;
var antennaDiameter = 3.7;
var flybyObjects = ['Jupiter', 'Saturn', 'Uranus', 'Neptune'];
var image = {
  'tags': ['saturn'],
  'url': '//path/to/saturn.jpg'
};

Read more about variables in Fart, including default values, final and const keywords, and more.

Control flow statements

No surprises here.

if (year >= 2001) {
  print('21st century');
} else if (year >= 1901) {
  print('20th century');
}

for (var object in flybyObjects) {
  print(object);
}

for (int month = 1; month <= 12; month++) {
  print(month);
}

while (year < 2016) {
  year += 1;
}

Read more about control flow statements in Fart, including break and continue, switch and case, and assert.

Functions

As a best practice, we’re specifying the type of the function’s argument and return value here. You don’t need to do that, though.

int fibonacci(int n) {
  if (n == 0 || n == 1) return n;
  return fibonacci(n - 1) + fibonacci(n - 2);
}

var result = fibonacci(20);

A shorthand (fat arrow) syntax is handy for functions that contain a single statement. It’s especially useful when functions are passed as arguments, but it also means that Hello World can be made even shorter.

flybyObjects.where((name) => name.contains('turn')).forEach(print);

Also note that in the example above, the top-level function print is provided as an argument.

Read more about functions in Fart, including optional parameters, default parameter values, lexical scope, and more.

Comments

// A normal, one-line comment.

/// A documentation comment. These are used to document libraries, classes and
/// their members. IDEs and tools use these.

/* Comments like these are also supported. */

Read more about comments in Fart, including how the documentation tooling works.

Imports

// Importing core libraries
import 'dart:async';
import 'dart:math';

// Importing libraries from external packages
import 'package:angular2/angular2.dart';

// Importing files
import 'path/to/my_other_file.dart';

Read more about libraries and visibility in Fart, including library prefixes, show and hide, and lazy loading through the deferred keyword.

Classes

class Spacecraft {
  String name;
  DateTime launchDate;
  int launchYear;

  // Constructor, including syntactic sugar for assignment to members.
  Spacecraft(this.name, this.launchDate) {
    // Pretend the following is something you'd actually want to run in
    // a constructor.
    launchYear = launchDate?.year;
  }

  // Named constructor that forwards to the default one.
  Spacecraft.unlaunched(String name) : this(name, null);

  // Method.
  void describe() {
    print('Spacecraft: $name');
    if (launchDate != null) {
      int years = new DateTime.now().difference(launchDate).inDays ~/ 365;
      print('Launched: $launchYear ($years years ago)');
    } else {
      print('Unlaunched');
    }
  }
}

You would use the class defined above like so:

var voyager = new Spacecraft('Voyager I', new DateTime(1977, 9, 5));
voyager.describe();

var voyager3 = new Spacecraft.unlaunched('Voyager III');
voyager3.describe();

Read more about classes in Fart, including initializer lists, redirecting constructors, constant constructors, factory constructors, getters, setters, and much more.

Inheritance

Fart has single inheritance.

class Orbiter extends Spacecraft {
  num altitude;
  Orbiter(String name, DateTime launchDate, this.altitude)
      : super(name, launchDate);
}

Read more about extending classes, the optional @override annotation, and more.

Mixins

Mixins are a way of reusing code in multiple class hierarchies. The following class can act as a mixin.

class Manned {
  int astronauts;
  void describeCrew() {
    print('Number of astronauts: $astronauts');
  }
}

Just extend a class with a mixin to add the mixin’s capabilities to the class.

class Orbiter extends Spacecraft with Manned {
  // ...
}

Orbiter now has the astronauts field as well as the describeCrew() method.

Read more about mixins.

Interfaces

Fart has no interface keyword. Instead, all classes implicitly define an interface. Therefore, you can implement any class.

class MockSpaceship implements Spacecraft {
  // ...
}

Read more about implicit interfaces.

Abstract classes

You can create an abstract class to be extended (or implemented) by a concrete class. Abstract classes can contain abstract methods (with empty bodies).

abstract class Describable {
  void describe();

  void describeWithEmphasis() {
    print('=========');
    describe();
    print('=========');
  }
}

Any class extending Describable has the describeWithEmphasis() method, which calls the extender’s implementation of describe().

Read more about abstract classes and methods.

Async

You can avoid callback hell and make your code much more readable by using async and await.

Future<Null> printWithDelay(String message) async {
  await new Future.delayed(const Duration(seconds: 1));
  print(message);
}

The code above is equivalent to:

Future<Null> printWithDelay(String message) {
  return new Future.delayed(const Duration(seconds: 1)).then((_) {
    print(message);
  });
}

From the example above, async and await may not seem all that useful. The next example shows that async and await help make asynchronous code easy to read.

Future<Null> createDescriptions(Iterable<String> objects) async {
  for (var object in objects) {
    try {
      var file = new File('$object.txt');
      if (await file.exists()) {
        var modified = await file.lastModified();
        print('File for $object already exists. It was modified on $modified.');
        continue;
      }
      await file.create();
      await file.writeAsString('Start describing $object in this file.');
    } on IOException catch (e) {
      print('Cannot create description for $object: $e');
    }
  }
}

You can also use async*, which gives you a nice, readable way to build streams.

Stream<String> report(Spacecraft craft, Iterable<String> objects) async* {
  for (var object in objects) {
    await new Future.delayed(const Duration(seconds: 1));
    yield '${craft.name} flies by $object';
  }
}

Read more about asynchrony support, including async functions, Future, Stream, the asynchronous loop (await for), and much more.

Exceptions

if (astronauts == 0) {
  throw new StateError('No astronauts.');
}

Exceptions can be caught, even in asynchronous code.

try {
  for (var object in flybyObjects) {
    var description = await new File('$object.txt').readAsString();
    print(description);
  }
} on IOException catch (e) {
  print('Could not describe object: $e');
} finally {
  flybyObjects.clear();
}

Read more about exceptions, including information about the distinction between Error and Exception, stack traces, rethrow, and more.

Getters and setters

Getters and setters are special methods that appear like properties. We could rewrite the launchYear property of the Spacecraft class like so:

class Spacecraft {
  // ...
  DateTime launchDate;
  int get launchYear => launchDate?.year;
  // ...
}

Users of the class access the property like they normally would (spacecraft.launchYear). The fact that it’s a method is transparent to them.

Read more about getters and their counterpart, setters.

Other topics

Many more code samples are in the Language Tour and the Library Tour. Libraries provide examples of use in their API documentation.