Shailen Tuli's blog

Thoughts on coding in Dart, Ruby, Python and Javascript

Character Codes and Strings in Dart

| Comments

In my Python programs, I found use for the ord() and chr() builtins to convert between string characters and their ASCII representations. Similar tools exist in Dart. To get a list of character codes for a string, use charCodes:

String s = "hello";
print(s.charCodes);
// [104, 101, 108, 108, 111]

To get a specific character code, you can either subscript charCodes:

print(s.charCodes[0]); 

or - this is the more common way - use charCodeAt:

print(s.charCodeAt(0));

To assemble a string from a list of character codes, use the String factory, fromCharCodes:

List<int> charCodes = [104, 101, 108, 108, 111];
print(new String.fromCharCodes(charCodes));
// "hello"

If you are using a StringBuffer to build up a string, you can add individual charCodes using addCharCode (use add() to add characters; use addCharCode() to add charCodes):

StringBuffer sb = new StringBuffer();
charCodes.forEach((charCode) {
  sb.addCharCode(charCode);
});

print(sb.toString());
// "Hello" 

Here is an implementation of the rot13 algorithm, using the tools described above. rot13 is a simple letter substitution algorithm that rotates a string by 13 places by replacing each character in it by one that is 13 characters removed (‘a’ becomes ‘n’, ‘N’ becomes ‘A’, etc.):

String rot13(String s) {
  List<int> rotated = [];

  s.charCodes.forEach((charCode) {
    final int numLetters = 26;
    final int A = 65;
    final int a = 97;
    final int Z = A + numLetters;
    final int z = a + numLetters;

    if (charCode < A ||
        charCode > z ||
        charCode > Z && charCode < a) {
      rotated.add(charCode);
    }
    else {
      if ([A, a].some((item){
        return item <= charCode && charCode < item + 13;
      })) {
        rotated.add(charCode + 13);
      } else {
        rotated.add(charCode - 13);
      }   
    }
  });

  return (new String.fromCharCodes(rotated));
}

Running the code:

var wordsList = [["Jung", "be", "purely", "barf"],
                  ["aha", "nun"]];
wordsList.forEach((word_list) {
  print(word_list.map((word) {
    return rot13(word);
  }));
});
// ["What", "or", "cheryl", "ones"]
// ["nun", "aha"] 

and:

String str = "aMz###AmZ";
assert(rot13(rot13(str)) == str);

Dart String Interpolation

| Comments

You can access the value of an expression inside a string by using ${expression}.

var greeting = "Hello";
var person = "Rohan";

print("${greeting}, ${person}!"); // prints "Hello, Rohan!"

If the expression is an identifier, the {} can be skipped.

print("$greeting, $person");

If the variable inside the {} isn’t a string, the variable’s toString() method is called:

int x = 5;
print("There are ${x.toString()} people in this room");

The call to toString() is unnecessary (although harmless) in this case: toString() is already defined for ints and Dart automatically calls toString(). What this does mean, though, is that it is the user’s responsibility to define a toString() method when interpolating user-defined objects.

You can interpolate expressions of arbitrary complexity by placing them inside ${}:

A ternary if..else:

int x = 5;
print("There are ${x < 10 ? "a few" : "many"} people in this room");

List and Map operations:

List list = [1, 2, 3, 4, 5];
print("The list is $list, and when squared it is ${list.map((i) {return i * i;})}");
// The list is [1, 2, 3, 4, 5], and when squared it is [1, 4, 9, 16, 25]

Map map = {"ca": "California", "pa": "Pennsylvania"};
print("I live in sunny ${map['ca']}");
// I live in sunny California

Notice above that you can access $list(an identifier) without using {}, but the call to list.map(an expression) needs to be inside {}. Similarly, in the example below, $x works, but {} are required for -x:

print("x = $x and -x = ${-x}");
// x = 5 and -x = -5

Expressions inside ${} can be arbitrarily complex:

List names = ['John', 'Sophena', 'Henrietta'];
print("${
  ((names) {
      return names[(new math.Random()).nextInt(names.length)];
  })(names)} is the most valueable member of our team");

The code above defines an anonymous function to pick a random name from a list and then calls that function with names as an argument. All of this is done as part of string interpolation.

Creating a function and immediately calling it is useful in a lot of situations (it is a common practice in Javascript); but, watch out: doing this sort of thing can lead to hard to maintain code. An abudance of caution is advised ;)

String Concatenation in Dart

| Comments

Let us start with a simple helloworld.dart example and use it to see how string concatenation works in Dart.

void main() {
  print("hello, world!");
}

The above works, obviously. Now, if we were given this greeting as two strings, “hello, ” and “world!”, and asked to join them together, we might be tempted to do:

"hello, " + "world!"

This works in lots of languages, but not in Dart. The + operator has not been overloaded in the String class, the above code throws a NoSuchMethodError.

Not a problem: Dart gives us lots of ways to contcatenate strings. I list the most common ways below. Above the examples you will see some crude benchmarks that I calculated by running each example a million times on my MacBook. These can give a general sense of the relative efficiency of each method.

The easiest, most efficient way to concat strings is by using adjacent string literals:

.041 seconds
String a = "hello, " "world!";

This still works if the adjacent strings are on different lines:

.040 seconds
String b = "hello, "
    'world!';

Dart also has a StringBuffer class, and this can be used to build up a StringBuffer object and convert it to a string by calling toString() on it:

.689 seconds
var sb = new StringBuffer();
["hello, ", "world!"].forEach((item) {
  sb.add(item);
  });
String c = sb.toString();

The Strings class (notice the plural) gives us 2 methods, join() and concatAll() that can also be used. Strings.join() takes a delimiter as a second argument:

.408 seconds
String d = Strings.join(["hello", "world!"], ", ");

.385 seconds
String e = Strings.concatAll(["hello", "world"]);

All of the above work, but if you are looking for a + substitute, use adjacent string literals; if you need to join a list of strings using a delimiter, use Strings.join(). If you plan on building a very long string, the StringBuffer class can gather the components quite efficiently and convert them to a string only when needed.

You can also use string interpolation; that will be the subject of my next post.

Why Use Dart?

| Comments

Building web applications is hard. Building large web applications is a real challenge. Given this, I am super excited by the emergence of Dart as a structured web programming language for building applications for the modern web.

I am mostly a Ruby and Python hacker. I have spent the last few years doing web programming and this means that I have spent a lot of time writing Javascript. I really like coding in Javascript: I like its (mostly) coherent OO/functional hybrid syntax, I find it expressive and I like to make use of its rich and rapidly evolving ecosystem of frameworks and libraries.

Javascript started off as small language for animating mostly static web pages. As the web has evolved, Javascript code-bases have become larger (my last project, a Rails 3 app using Backbone, had more Javascript than Ruby code in it). Large codebases require careful use of code reuse and organization if they are to scale; through the use of ‘classes’ and inheritance, the module and sandbox design patterns, popular MVC frameworks like Backbone and Angular, Javascript developers have sought to bring more structure to their code.

I very much view Dart as a logical next step in this quest for greater code organization. The Dart project is a serious - and long awaited - attempt at creating an alternative to writing web applications using Javascript; it is likely to appeal to those who want to retain the relative ease of current web development, but want a language with more structure than what is available to them today. Building large web applications has been quite daunting - even heroic - and Dart aims to make the development process easier. Dart is a “batteries included” project (the language comes with libraries, a package manager, an editor, and a VM) and Dart code executes fast, making it an attractive option for modern web development.

Here are a few salient points about Dart:

  • Dart is open source
  • it has a syntax that is likely to be familiar to most programmers
  • it is relatively easy to learn
  • it compiles to javascript that can be run in any modern browser
  • it can also be executed directly using a Chromium-based browser (nicknamed Dartium) that includes the Dart virtual machine (VM)
  • it can coexist with javascript through the use of the interop library
  • it runs in the client and the server
  • it comes with a lightweight editor that you can use to write and debug applications
  • Dart programs run fast (many of the people who created Chrome’s V8 are leading the Dart project)
  • it offers concurrency through the use of isolates
  • Dart has optional static type anotations that can help you organize your code, provide better debug messages in the editor and act as documentation
  • it comes with batteries included: an HTML library for DOM manipulation, an IO library and a unittest library
  • it encourages modular code organization through the use of libraries
  • it has a package manager (pub) so you can integrate code from across the Dart ecosystem

Is Dart going to change how we write web applications? While its still early - the language just had its M1 (Milestone 1) release and is still not at the 1.0 stage - what I see so far is super encouraging.

Starting to Blog With Octopress

| Comments

I recently started working at Google. I expect to be writing in this space about Dart, HTML5, Web Components and whatever else I encounter that might be interesting to anyone else.

This blog is created using Octopress, a framework designed for Jekyll, the static blogging engine that powers Github Pages. Using Octopress, I can use Markdown, embed code from my filesystem, download and embed gists, embed code from jsFiddle, and publish easily via a git push.