Dart: Using prefix for #import

Using “prefix” is great for managing how your application references libraries in Dart. At the moment Dart is still in alpha so this exact method or style may change at some later date. From the Language Specification (0.06) Libraries have a very simple definition.

A library consists of (a possibly empty) set of imports, and a set of top level
declarations. A top level declaration is either a class (7), an interface (8), a type
declaration, a function (6) or a variable declaration (5).

Lets dive in and create one main application and one cipher application that will be a library.

Now if we #import CipherLib from filesystem path into our MainApplication both main functions should conflict.

Why this happens is clearly defined in the specification.

Imports assume a global namespace of libraries (at least per isolate). They also assume the library is in control, rather than the other way around. It is a compile-time error if a name N is introduced into the library scope of a library A, and either: N is declared by A, OR Another import introduces N into the scope of A. This implies that it is a load-time error for a library to import itself, as the names of its members will be duplicated.

The MainAppication can be adjusted by adding the prefix parameter to the #import declaration. Now from the prefixed name we can call the main method.

From this point lets add another library, will call it XORCipher which will call its library “CipherLib”. The XORCipher and CaesarCipher will have libraries named “CipherLib”, both have functions that have the same name but take different parameters. Now we shall run into a problem that could be presented when using others libraries or code, we have conflicting names in the global namespace of our main application.

The way we resolve this is by adding prefix to one or both libraries and call them from the fully qualified names.

#import('../CaesarCipher/CaesarCipher.dart', prefix:"Caesar");
#import('../XORCipher/XORCipher.dart', prefix:"XOR");

void main() {
  String s = "HELLOWORLD";
  s = XOR.EncryptDecrypt(s);
  print("After encrypt XOR ${s}");
  s = XOR.EncryptDecrypt(s);
  print("After decrypt XOR ${s}");
  s = Caesar.EncryptDecrypt(s, true);
  print("After encrypt Caesar ${s}");
  s = Caesar.EncryptDecrypt(s, false);
  print("After decrypt Caesar ${s}");

Another way to encapsulate source code using libraries is to use the #source declaration in a #library and then to #import the library into your application. From the language specifications:

An include directive specifics a URI where a Dart compilation unit that should be incorporated into the current library may be found. A compilation unit is a sequence of top level declarations. Compiling an include directive of the form #source(s); causes the Dart system to attempt to compile the contents of the URI that is the value of s. The top level declarations at that URI are then compiled by the Dart compiler in the scope of the current library. It is a compile-time error if the contents of the URI are not a valid compilation unit. It is a compile-time error if s is not a compile-time constant.

An example of this type of library can be seen in HashLib/hashlib.dart:



Another great example of this can be seen in John Evans LUCA UI Framework unit test code. He needed access to some internal dom objects but wanted to preserve the ability to use the elegantly designed html library.

#import('dart:dom', prefix:'dom');

Its not uncommon to run into instances where two libraries or source files may define classes, interfaces, functions, type definitions that have similar names in other libraries or source files. The best way to work in these types of situations is to add a prefix where your #import are. A very common one that people run into is with “html”, Node and Element class. So individuals wanting to create some type of search or sorting might also want to use the Node name, best answer would be to prefix “html” or your own library code. After your able to reference the library by its fully qualified name, instead of assuming it was globally included. This does feel similar to the using alias in C#, but with a feeling of inversion of control to the library.

Sample code dart-using-prefix-example
Language specification

Dartium Build rev 116980 in 4 easy steps

At the moment Dartium builds are not available on Googles continuous integration server. So I decided to distribute a release build for Linux 32bit . Based on the wiki directions its simple enough for anyone to generate, I felt the need to distribute a build for those who don’t have the time to invest in downloading/configuring/building. An important tip testing dart code in Dartium is to include the additional script call that executes the entry into main(). This is done by adding an additional <script>{}</script> following the line where the dart code is loaded.

The build of Dartium provide is from Rev: 116980

  • Get the latest version of DartEditor and Dartium

wget http://gsdview.appspot.com/dart-editor-archive-continuous/latest/DartBuild-linux.gtk.x86.zip
wget http://dl.dropbox.com/u/33138127/dartium/dartium-linux-32bit-Release.tar.gz
wget http://dl.dropbox.com/u/33138127/dartium/dartium-linux-32bit-Release.tar.gz.md5
wget http://dl.dropbox.com/u/33138127/dartium/README.txt
md5sum -c dartium-linux-32bit-Release.tar.gz.md5
  • Register Dartium on Ubuntu as a registered application so DartEditor can pick it up. Modify dartium-browser.desktop to the chrome-wrapper where Dartium was unzipped.
wget http://dl.dropbox.com/u/33138127/dartium/dartium-browser.desktop
vim dartium-browser.desktop
wget http://dl.dropbox.com/u/33138127/dartium/dartium-browser.desktop.ubuntu.install.sh
sudo ./dartium-browser.desktop.ubuntu.install.sh
  • Register Dartium as the browser to launch in DartEditor

  • Create a famous HelloWorld.

Adjust the html to properly execute dart.

Watch dart in its metal state.



Unit testing in DartEditor Alpha

Original Document can be found here


Get every new post delivered to your Inbox.