Strings in Dart
UPDATED: 2013-07-01
(This is part 7 in an ongoing series about Dart. Check out part 6, For loops in Dart.)
Dart brings some new ideas to Strings. If you think you know Strings, keep reading for a few surprises.
From the API docs: "A string is represented by a sequence of Unicode UTF-16 code units."
Immutable
String are immutable objects, which means you can create them but you can't change them. You can of course build a new string out of other strings, but once created, the string's contents are fixed.
This is an optimization, as two strings with the same characters in the same order can be the same object.
If you look closely at the String API docs, you'll notice that none of the methods on String actually change the state of a String. For example, the method replaceAll() returns a new String and doesn't exchange the original String.
Creating
Both single and double quotes can be used to declare a String.
Multi-line strings are now supported! Just use a triple quote (''' or """), with either single quote or double quote. Note the initial newline is ignored, but the last newline is not ignored!
Escaping
Some languages interpret single quotes as a "literal" string, but not Dart.
You can make a "raw" string by prefixing it with r. For example:
Interpolation
Dart improves on other web programming languages by introducing string interpolation. Building and joining strings is much easier now:
Building from parts
Programmatically generating a String is best accomplished with a StringBuffer. A StringBuffer doesn't generate a new String object until toString() is called.
You might be thinking, "Pffft, typing StringBuffer is so many characters. The performance difference can't be that big of a deal!" to which I reply, "The numbers don't lie."
As you can see, using old school + concatenation for Strings is much slower than using StringBuffer.
Note: the above times were measured in the Dart VM. When compiled to JavaScript, you will see different numbers.
Matching
Thanks to the core Dart libraries, it's fairly easy to determine if a strings starts with, ends with, or contains another string.
The contains() method can also take a RegExp object for the pattern.
Summary
Strings are immutable lists of Unicode UTF-16 code units. They can be multi-line with triple quotes, or "raw" and unfiltered with a @ prefix.
Strings can be interpolated, which is preferable to concatenation via the + operator. If you must programmatically build up a String, do so with StringBuffer, which is much faster.
Strings can do a lot more than we showed here. For instance, you can split a string, create a substring, trim it, and lots more.
Next Steps
Like what you see? Learn more about Dart, its HTML libraries, and join the discussion. File a new issue if you see something missing.
Also, follow @dart_lang and +Dartisans for more info!
Read Part 8, This is this in Dart, in which we no longer have to assign this to _this for closures.
(This is part 7 in an ongoing series about Dart. Check out part 6, For loops in Dart.)
Dart brings some new ideas to Strings. If you think you know Strings, keep reading for a few surprises.
From the API docs: "A string is represented by a sequence of Unicode UTF-16 code units."
Immutable
String are immutable objects, which means you can create them but you can't change them. You can of course build a new string out of other strings, but once created, the string's contents are fixed.
This is an optimization, as two strings with the same characters in the same order can be the same object.
var s11 = "strings are immutable";
var s21 = "strings are immutable";
print(s11 == s21); // true, contain the same characters
print(identical(s11, s21)); // true, are the same object in memory
If you look closely at the String API docs, you'll notice that none of the methods on String actually change the state of a String. For example, the method replaceAll() returns a new String and doesn't exchange the original String.
var greetingTemplate = 'Hello NAME, nice to meet you!';
var greeting = greetingTemplate.replaceFirst(new RegExp("NAME"), 'Bob');
print(greetingTemplate != greeting); // true
Creating
Both single and double quotes can be used to declare a String.
print('single quotes work easily'); print("double quotes work just as well");
Multi-line strings are now supported! Just use a triple quote (''' or """), with either single quote or double quote. Note the initial newline is ignored, but the last newline is not ignored!
print( ''' the initial newline is ignored but the last newline is not ignored '''); // is the same as print("""the initial newline is ignored but the last newline is not ignored\n""");
Escaping
Some languages interpret single quotes as a "literal" string, but not Dart.
print('single quotes \n don\'t make a string literal');
> single quotes
don't make a string literal
You can make a "raw" string by prefixing it with r. For example:
print(r'prefixing with a r turns a string into a \n literal or "raw" string');
> prefixing with a r turns a string into a \n literal or "raw" string
Interpolation
Dart improves on other web programming languages by introducing string interpolation. Building and joining strings is much easier now:
var s = 'string interpolation'; print('dart has ${s} which is very handy'); print("you can nest ${s + ' for fun and ${"profit"}'} with Dart"); print("concatenating strings" + " " + "is also possible with the plus sign");
> dart has string interpolation which is very handy > you can nest string interpolation for fun and profit with Dart > concatenating strings is also possible with the plus sign, but we don't recommend it
Building from parts
Programmatically generating a String is best accomplished with a StringBuffer. A StringBuffer doesn't generate a new String object until toString() is called.
var sb = new StringBuffer(); sb.write("Use a StringBuffer"); sb.writeAll(["for ", "efficient ", "string ", "creation "]); sb.write("if you are ") sb.write("building lots of strings"); // or you can use method cascades: sb ..write("Use a StringBuffer") ..writeAll(["for ", "efficient ", "string ", "creation "]) ..write("if you are ") ..write("building lots of strings"); var fullString = sb.toString(); print(fullString); // Use a StringBufferfor efficient string creation if you are building lots of strings sb.clear(); // all gone!
You might be thinking, "Pffft, typing StringBuffer is so many characters. The performance difference can't be that big of a deal!" to which I reply, "The numbers don't lie."
// use new hotness: StringBuffer buildWithStringBuffer() { var sb = new StringBuffer(); for (var i = 9999; i > 0; i--) { sb.add(i.toString()); sb.add(" beers on the wall\n"); } var finalString = sb.toString(); } // use old school + for string concatenation buildWithConcat() { var s = ''; for (var i = 9999; i > 0; i--) { s += i.toString(); s += " beers on the wall\n"; } var finalString = s; } // wrap a function fn with the Stopwatch class to time execution measure(fn) { var sw = new Stopwatch.start(); fn(); return sw.elapsedInMs(); } // the following timings are from the Dart VM // smaller is faster is better measure(buildWithStringBuffer); // 20 measure(buildWithConcat); // 3574 !!
As you can see, using old school + concatenation for Strings is much slower than using StringBuffer.
Note: the above times were measured in the Dart VM. When compiled to JavaScript, you will see different numbers.
Matching
Thanks to the core Dart libraries, it's fairly easy to determine if a strings starts with, ends with, or contains another string.
var fullName = 'Cuthbert Musgrave Girdlestone, III'; fullName.startsWith('Cuthbert'); // true fullName.endsWith('III'); // true fullName.contains('Musgrave'); // true
The contains() method can also take a RegExp object for the pattern.
Summary
Strings are immutable lists of Unicode UTF-16 code units. They can be multi-line with triple quotes, or "raw" and unfiltered with a @ prefix.
Strings can be interpolated, which is preferable to concatenation via the + operator. If you must programmatically build up a String, do so with StringBuffer, which is much faster.
Strings can do a lot more than we showed here. For instance, you can split a string, create a substring, trim it, and lots more.
Next Steps
Like what you see? Learn more about Dart, its HTML libraries, and join the discussion. File a new issue if you see something missing.
Also, follow @dart_lang and +Dartisans for more info!
Read Part 8, This is this in Dart, in which we no longer have to assign this to _this for closures.