Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(23)

Side by Side Diff: src/site/articles/m1-language-changes/index.markdown

Issue 10700168: massive CL is massive (Closed) Base URL: https://code.google.com/p/dartlang-site/@master
Patch Set: Created 8 years, 5 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 --- 1 ---
2 layout: default 2 layout: default
3 title: "Milestone 1 Language Changes" 3 title: "Milestone 1 Language Changes"
4 rel: 4 rel:
5 author: bob-nystrom 5 author: bob-nystrom
6 description: "A brief introduction to some of the language changes we are making heading into our next milestone." 6 description: "A brief introduction to some of the language changes planned for t he M1 milestone."
7 --- 7 ---
8 8
9 # Milestone 1 Language Changes 9 # Milestone 1 Language Changes
10 10
11 Right now as we near our Milestone 1 release, we are making a slew of fun lang uage changes. There are tracking bugs in the repo for all of them, but I wanted to run through them here and try to provide some context and rationale where I c an. 11 Right now as we near our "Milestone 1" release, we are making a slew of fun lang uage changes. There are tracking bugs in the repo for all of them, but I wanted to run through them here and try to provide some context and rationale where I c an.
12 12
13 ## Contents 13 ## Contents
14 14
15 1. [No explicit interfaces](#no-explicit-interfaces) 15 1. [No explicit interfaces](#no-explicit-interfaces)
16 1. [No "+" on String](#no--on-string) 16 1. [No "+" on String](#no--on-string)
17 1. [No throwing `null`](#no-throwing-null) 17 1. [No throwing `null`](#no-throwing-null)
18 1. [The as cast operator](#the-as-cast-operator) 18 1. [The "as" cast operator](#the-as-cast-operator)
19 1. [Cascades](#cascades) 19 1. [Cascades](#cascades)
20 1. [Lazy static initialization](#lazy-static-initialization) 20 1. [Lazy static initialization](#lazy-static-initialization)
21 1. [Support const modifier for variables](#support-const-modifier-for-variable s) 21 1. [Support "const" modifier for variables](#support-const-modifier-for-variable s)
22 1. [Syntax for defining operators](#syntax-for-defining-operators) 22 1. [Syntax for defining operators](#syntax-for-defining-operators)
23 1. [Split library scope and import scope](#split-library-scope-and-import-scope) 23 1. [Split library scope and import scope](#split-library-scope-and-import-scope)
24 1. [Revised switch](#revised-switch) 24 1. [Revised switch](#revised-switch)
25 1. [Selective imports](#selective-imports) 25 1. [Selective imports](#selective-imports)
26 1. [Re-export](#re-export) 26 1. [Re-export](#re-export)
27 1. [Static methods are constants](#static-methods-are-constants) 27 1. [Static methods are constants](#static-methods-are-constants)
28 1. [New catch syntax](#new-catch-syntax) 28 1. [New catch syntax](#new-catch-syntax)
29 1. [Getter and setter definition syntax](#getter-and-setter-definition-syntax) 29 1. [Getter and setter definition syntax](#getter-and-setter-definition-syntax)
30 1. [Conclusion](#conclusion) 30 1. [Conclusion](#conclusion)
31 {:.toc} 31 {:.toc}
(...skipping 25 matching lines...) Expand all
57 {% endhighlight %} 57 {% endhighlight %}
58 58
59 Note that it says *implements*, not *extends*. We are not subclassing Person, we are just saying that Imposter supports all of the public methods Person defines and that we can pass it to anything that expects a Person. 59 Note that it says *implements*, not *extends*. We are not subclassing Person, we are just saying that Imposter supports all of the public methods Person defines and that we can pass it to anything that expects a Person.
60 60
61 Dart also supports abstract methods in classes. Given abstract methods and impli cit interfaces, there’s no actual need for an explicit interface construct: just make a class where all of its methods are abstract, and then implement its impl icit interface. 61 Dart also supports abstract methods in classes. Given abstract methods and impli cit interfaces, there’s no actual need for an explicit interface construct: just make a class where all of its methods are abstract, and then implement its impl icit interface.
62 62
63 Getting rid of interfaces simplifies the language while also removing some of th e limitations that interfaces had: unlike classes, they couldn’t define static m embers for example. It also simplifies designing an API: you no longer have thin k about whether you should define something as an interface or an abstract class . 63 Getting rid of interfaces simplifies the language while also removing some of th e limitations that interfaces had: unlike classes, they couldn’t define static m embers for example. It also simplifies designing an API: you no longer have thin k about whether you should define something as an interface or an abstract class .
64 64
65 ## No "+" on String 65 ## No "+" on String
66 66
67 A deeply contentious issue, Dart no longer allows using the “+” operator on stri ngs. So no more: 67 A deeply contentious issue, Dart no longer allows using the "+" operator on stri ngs. So no more:
68 68
69 {% highlight dart %} 69 {% highlight dart %}
70 print("Hi, " + yourName); 70 print("Hi, " + yourName);
71 {% endhighlight %} 71 {% endhighlight %}
72 72
73 There seem to be as many reasons for (and against) this change as there are Dart team members, but the two motivators I see repeatedly are: 73 There seem to be as many reasons for (and against) this change as there are Dart team members, but the two motivators I see repeatedly are:
74 74
75 1. It’s a source of bugs and surprising behavior because it’s not symmetric and is sensitive to operator precedence. `print("1 + 2 = " + 1 + 2)` doesn’t do what some people might expect and `"a" + 1` and `1 + "a"` have unpleasantly differen t behavior. 75 1. It’s a source of bugs and surprising behavior because it’s not symmetric and is sensitive to operator precedence. `print("1 + 2 = " + 1 + 2)` doesn’t do what some people might expect and `"a" + 1` and `1 + "a"` have unpleasantly differen t behavior.
76 76
77 2. Naïve code that uses it heavily can have poor performance with simple interna l string implementations. If you do something like use `+=` in a loop to build u p a long string, and you’re running on an implementation that doesn’t have sophi sticated code for handling strings you can end up doing a lot of wasted allocati ons. 77 2. Naïve code that uses it heavily can have poor performance with simple interna l string implementations. If you do something like use `+=` in a loop to build u p a long string, and you’re running on an implementation that doesn’t have sophi sticated code for handling strings you can end up doing a lot of wasted allocati ons.
78 78
79 So, without `+`, what should you do when you need to staple a couple of strings to each other? Fortunately, [Seth has your back here](http://news.dartlang.org/2 012/06/vm-to-remove-support-for-string.html). 79 So, without `+`, what should you do when you need to staple a couple of strings to each other? Fortunately, [Seth has your back here](http://news.dartlang.org/2 012/06/vm-to-remove-support-for-string.html).
80 80
81 ([Tracking issue #3707](http://dartbug.com/3707)) 81 ([Tracking issue #3707](http://dartbug.com/3707))
82 82
83 ## No throwing `null` 83 ## No throwing `null`
84 84
85 Dart now considers it a dynamic error to throw `null`. In almost every case wher e `null` is thrown, it’s a programmer error: they meant to throw some exception object but accidentally got a `null` instead. By disallowing this, we can detect that error earlier and help the user fix their code. 85 Dart now considers it a dynamic error to throw `null`. In almost every case wher e `null` is thrown, it’s a programmer error: they meant to throw some exception object but accidentally got a `null` instead. By disallowing this, we can detect that error earlier and help the user fix their code.
86 86
87 *Allowing* `null` to be thrown, on the other hand, forces programmers to think a bout what kinds of `catch` clauses will match it. Will a `catch` clause of any t ype select `null`? None of them? Just `var ex`? There isn’t an obvious intuitive correct behavior here, so users are likely to be confused. 87 *Allowing* `null` to be thrown, on the other hand, forces programmers to think a bout what kinds of `catch` clauses will match it. Will a `catch` clause of any t ype select `null`? None of them? Just `var ex`? There isn’t an obvious intuitive correct behavior here, so users are likely to be confused.
88 88
89 ([Tracking issue #2940](http://dartbug.com/2940)) 89 ([Tracking issue #2940](http://dartbug.com/2940))
90 90
91 ## The as cast operator 91 ## The "as" cast operator
92 92
93 Dart now has an infix operator `as` that lets you cast an expression to a given type without having to declare a type annotated local variable. Where before, if you wanted to indicate some extra knowledge about the types of objects in your code, you had to do: 93 Dart now has an infix operator `as` that lets you cast an expression to a given type without having to declare a type annotated local variable. Where before, if you wanted to indicate some extra knowledge about the types of objects in your code, you had to do:
94 94
95 {% highlight dart %} 95 {% highlight dart %}
96 ButtonElement button = query('button'); 96 ButtonElement button = query('button');
97 button.value = 1234; 97 button.value = 1234;
98 {% endhighlight %} 98 {% endhighlight %}
99 99
100 Now you can do: 100 Now you can do:
101 101
(...skipping 19 matching lines...) Expand all
121 121
122 or the tedium of having to define a local variable: 122 or the tedium of having to define a local variable:
123 123
124 {% highlight dart %} 124 {% highlight dart %}
125 var toggleButton = query('#my-form').query('button'); 125 var toggleButton = query('#my-form').query('button');
126 toggleButton.classes.add('toggle'); 126 toggleButton.classes.add('toggle');
127 toggleButton.text = 'Click Me!'; 127 toggleButton.text = 'Click Me!';
128 toggleButton.labels.add(toggleLabel); 128 toggleButton.labels.add(toggleLabel);
129 {% endhighlight %} 129 {% endhighlight %}
130 130
131 Some APIs, like jQuery in JavaScript or StringBuffer in Java get around this by using fluent interfaces: their methods return this so you can chain calls dire ctly. But that forces API designers to choose between returning a useful value o r allowing chaining: they can’t support both. It also forces all APIs to be desi gned up front to support this. 131 Some APIs, like jQuery in JavaScript or StringBuffer in Java get around this by using "fluent interfaces": their methods return this so you can chain calls dire ctly. But that forces API designers to choose between returning a useful value o r allowing chaining: they can’t support both. It also forces all APIs to be desi gned up front to support this.
132 132
133 To remedy that, Smalltalk pioneered something called message cascades which Da rt has adopted. These let you sequence a series of method calls that all apply t o the same receiver, like so: 133 To remedy that, Smalltalk pioneered something called "message cascades" which Da rt has adopted. These let you sequence a series of method calls that all apply t o the same receiver, like so:
134 134
135 {% highlight dart %} 135 {% highlight dart %}
136 query('#my-form').query('button') 136 query('#my-form').query('button')
137 ..classes.add('toggle') 137 ..classes.add('toggle')
138 ..text = 'Click Me!' 138 ..text = 'Click Me!'
139 ..labels.add(toggleLabel); 139 ..labels.add(toggleLabel);
140 {% endhighlight %} 140 {% endhighlight %}
141 141
142 Here, everything after `..` is called on the result of the expression before the first `..`. What’s nice is that this works with every API, not just ones explic itly implemented using a fluent pattern. 142 Here, everything after `..` is called on the result of the expression before the first `..`. What’s nice is that this works with every API, not just ones explic itly implemented using a fluent pattern.
143 143
144 ([Tracking issue #2501](http://dartbug.com/2501)) 144 ([Tracking issue #2501](http://dartbug.com/2501))
145 145
146 ## Lazy static initialization 146 ## Lazy static initialization
147 147
148 Formerly, Dart required that all `static final` fields (or `final` top-level var iables) be initialized with constant expressions. In other words, they could onl y be used to define compile-time constants. That significantly limits their use, preventing, for example, this field: 148 Formerly, Dart required that all `static final` fields (or `final` top-level var iables) be initialized with constant expressions. In other words, they could onl y be used to define compile-time constants. That significantly limits their use, preventing, for example, this field:
149 149
150 {% highlight dart %} 150 {% highlight dart %}
151 class Stopwatch { 151 class Stopwatch {
152 static final startTime = new DateTime.now(); 152 static final startTime = new DateTime.now();
153 } 153 }
154 {% endhighlight %} 154 {% endhighlight %}
155 155
156 We’ve decided to loosen that so that `static final` fields and `final` top-level variables can be initialized using *any* expression. These will then be lazy in itialized the first time the variable is accessed. This is closer to behavior us ers coming from Java or C# expect given Dart’s similar syntax. 156 We’ve decided to loosen that so that `static final` fields and `final` top-level variables can be initialized using *any* expression. These will then be lazy in itialized the first time the variable is accessed. This is closer to behavior us ers coming from Java or C# expect given Dart’s similar syntax.
157 157
158 ([Tracking issue #3557](http://dartbug.com/3557)) 158 ([Tracking issue #3557](http://dartbug.com/3557))
159 159
160 ## Support const modifier for variables 160 ## Support "const" modifier for variables
161 161
162 The above change is more flexible, but it leaves an open issue: how do you defin e a `static final` field or `final` top-level variable that *is* constant, and t hat can be used in constant expressions? With this looser behavior, you lose the ability to do: 162 The above change is more flexible, but it leaves an open issue: how do you defin e a `static final` field or `final` top-level variable that *is* constant, and t hat can be used in constant expressions? With this looser behavior, you lose the ability to do:
163 163
164 {% highlight dart %} 164 {% highlight dart %}
165 class SomeClass { 165 class SomeClass {
166 static final someConstant = 123; 166 static final someConstant = 123;
167 static final aConstList = const [someConstant]; 167 static final aConstList = const [someConstant];
168 } 168 }
169 {% endhighlight %} 169 {% endhighlight %}
170 170
171 Since `someConstant` doesn’t *have* to be constant now, it may not be, which mea ns it can’t be used in a constant expression like `const [someConstant]`. To fix that, Dart will also allow `const` as a modifier for variables. This way you ca n indicate which top-level `final` variables and `static final` fields are const ant and which are lazy-initialized non-constant: 171 Since `someConstant` doesn’t *have* to be constant now, it may not be, which mea ns it can’t be used in a constant expression like `const [someConstant]`. To fix that, Dart will also allow `const` as a modifier for variables. This way you ca n indicate which top-level `final` variables and `static final` fields are const ant and which are lazy-initialized non-constant:
172 172
173 {% highlight dart %} 173 {% highlight dart %}
174 class SomeClass { 174 class SomeClass {
175 static const someConstant = 123; // OK 175 static const someConstant = 123; // OK
176 static final startTime = new DateTime.now(); // OK too 176 static final startTime = new DateTime.now(); // OK too
177 static const aConstList = const [someConstant]; // also OK 177 static const aConstList = const [someConstant]; // also OK
178 } 178 }
179 {% endhighlight %} 179 {% endhighlight %}
180 180
181 ([Tracking issue #3549](http://dartbug.com/3549)) 181 ([Tracking issue #3549](http://dartbug.com/3549))
182 182
183 ## Syntax for defining operators 183 ## Syntax for defining operators
184 184
185 This is a pretty minor change. The previous spec used `equals` and `negate` as s pecial identifiers for defining equality and unary negation operators, respectiv ely. That raises some confusing questions like Can you also call those methods by name? To simplify that, we will just use `==` and `-` to define those operat ors. We’ll disambiguate unary and binary minus by their arity (number of paramet ers). 185 This is a pretty minor change. The previous spec used `equals` and `negate` as s pecial identifiers for defining equality and unary negation operators, respectiv ely. That raises some confusing questions like "Can you also call those methods by name?" To simplify that, we will just use `==` and `-` to define those operat ors. We’ll disambiguate unary and binary minus by their arity (number of paramet ers).
186 186
187 {% highlight dart %} 187 {% highlight dart %}
188 class MagicNumber { 188 class MagicNumber {
189 bool operator ==(other) => … 189 bool operator ==(other) => …
190 MagicNumber operator -() => … // unary negate 190 MagicNumber operator -() => … // unary negate
191 MagicNumber operator -(other) => … // infix minus 191 MagicNumber operator -(other) => … // infix minus
192 } 192 }
193 {% endhighlight %} 193 {% endhighlight %}
194 194
195 ([Tracking issue #3765](http://dartbug.com/3765)) 195 ([Tracking issue #3765](http://dartbug.com/3765))
196 196
197 ## Split library scope and import scope 197 ## Split library scope and import scope
198 198
199 Stephen [explains the rationale for this change](http://code.google.com/p/dart/i ssues/detail?id=1285) better than I can: 199 Stephen [explains the rationale for this change](http://code.google.com/p/dart/i ssues/detail?id=1285) better than I can:
200 200
201 > There is a problem that a name may be defined by `#import` or by a definition in the current library. A change to the imported library can break a program by introducing a clashing name. 201 > There is a problem that a name may be defined by `#import` or by a definition in the current library. A change to the imported library can break a program by introducing a clashing name.
202 202
203 What he means here is consider you have this program: 203 What he means here is consider you have this program:
204 204
205 {% highlight dart %} 205 {% highlight dart %}
206 #import('somelib.dart'); 206 #import('somelib.dart');
207 207
208 foo() => print('foo!'); 208 foo() => print('foo!');
209 main() => foo(); 209 main() => foo();
210 {% endhighlight %} 210 {% endhighlight %}
211 211
212 Later, you upgrade to the latest greatest version of somelib and discover to y our dismay that they’ve added a `foo()` function to it. Currently, this breaks y our code since those names are in the same namespace and collide. Stephen’s prop osal is: 212 Later, you upgrade to the latest greatest version of "somelib" and discover to y our dismay that they’ve added a `foo()` function to it. Currently, this breaks y our code since those names are in the same namespace and collide. Stephen’s prop osal is:
213 213
214 > I suggest that imports happen into a scope surrounding the current library. T his would reduce a clash in an imported library to an override warning and at th e same time ensure the current library's behaviour did not change. 214 > I suggest that imports happen into a scope surrounding the current library. T his would reduce a clash in an imported library to an override warning and at th e same time ensure the current library's behaviour did not change.
215 215
216 In other words, with this change, your local `foo()` will *shadow* the new one i n somelib instead of colliding, and your code does the right thing. 216 In other words, with this change, your local `foo()` will *shadow* the new one i n "somelib" instead of colliding, and your code does the right thing.
217 217
218 In addition, we’ve removed another annoying restriction. Previously, if you impo rted the same name from two different libraries (say Node from dart:html and dar tdoc) then you would get a name collision error *even if you didn’t use that nam e anywhere in your code.* Now, Dart will only worry about name collisions for na mes that you actually use. You only get an error if there is an ambiguous *use* of a name in your code. 218 In addition, we’ve removed another annoying restriction. Previously, if you impo rted the same name from two different libraries (say Node from dart:html and dar tdoc) then you would get a name collision error *even if you didn’t use that nam e anywhere in your code.* Now, Dart will only worry about name collisions for na mes that you actually use. You only get an error if there is an ambiguous *use* of a name in your code.
219 219
220 ([Tracking issue #1285](http://dartbug.com/1285)) 220 ([Tracking issue #1285](http://dartbug.com/1285))
221 221
222 ## Revised switch 222 ## Revised switch
223 223
224 In its original incarnation, Dart’s `switch` statement worked like JavaScript’s and not Java’s. It was essentially syntactic sugar for a series of chained `if-e lse` statments. For example, this: 224 In its original incarnation, Dart’s `switch` statement worked like JavaScript’s and not Java’s. It was essentially syntactic sugar for a series of chained `if-e lse` statments. For example, this:
225 225
226 {% highlight dart %} 226 {% highlight dart %}
(...skipping 14 matching lines...) Expand all
241 hasBeard = true; 241 hasBeard = true;
242 } else { 242 } else {
243 hasBeard = false; 243 hasBeard = false;
244 } 244 }
245 {% endhighlight %} 245 {% endhighlight %}
246 246
247 Note that in the desugared `if-else` form, it ends up calling the equality (`==` ) operator. This operator can be overloaded for your own types, so this has an i mportant consequence. With these semantics, a `switch` statement *must* be handl ed exactly like a series of chained `if-else` statements. 247 Note that in the desugared `if-else` form, it ends up calling the equality (`==` ) operator. This operator can be overloaded for your own types, so this has an i mportant consequence. With these semantics, a `switch` statement *must* be handl ed exactly like a series of chained `if-else` statements.
248 248
249 This has unpleasant optimization implications. In languages like C and Java, a ` switch` statement can only be used with numeric values. Compilers can and do com pile down a `switch` statement to either a jump table that directly selects a ca se based on the value, or to a binary search of the cases, or some mixed heurist ic of the two. In other words, in those languages selecting the right `case` for a `switch` can have `O(1)` or `O(log n)` performance (where `n` is the number o f cases). In Dart, it’s always `O(n)`. 249 This has unpleasant optimization implications. In languages like C and Java, a ` switch` statement can only be used with numeric values. Compilers can and do com pile down a `switch` statement to either a jump table that directly selects a ca se based on the value, or to a binary search of the cases, or some mixed heurist ic of the two. In other words, in those languages selecting the right `case` for a `switch` can have `O(1)` or `O(log n)` performance (where `n` is the number o f cases). In Dart, it’s always `O(n)`.
250 250
251 So we’ve decided to restrict `switch` in Dart. Instead of calling a user-defined equality operator, we only allow you to switch on numbers, strings, and constan t objects. This gives compilers enough flexibility to compile them more efficien tly. Since constant objects are canonicalized, they can be reliably compared pur ely based on *identity*, so they don’t have the problem of allowing user-defined equality operators. This lets you still switch on user-defined enum-like obje cts. 251 So we’ve decided to restrict `switch` in Dart. Instead of calling a user-defined equality operator, we only allow you to switch on numbers, strings, and constan t objects. This gives compilers enough flexibility to compile them more efficien tly. Since constant objects are canonicalized, they can be reliably compared pur ely based on *identity*, so they don’t have the problem of allowing user-defined equality operators. This lets you still switch on user-defined "enum-like" obje cts.
252 252
253 ## Selective imports 253 ## Selective imports
254 254
255 Library imports were a blunt instrument in Dart: you either imported every singl e name from a library or none of them. If a single name in that library collides with another one you’re importing, your only recourse is to import that entire library with a prefix. 255 Library imports were a blunt instrument in Dart: you either imported every singl e name from a library or none of them. If a single name in that library collides with another one you’re importing, your only recourse is to import that entire library with a prefix.
256 256
257 Now, you’ll be given finer grained control. If you do: 257 Now, you’ll be given finer grained control. If you do:
258 258
259 {% highlight dart %} 259 {% highlight dart %}
260 #import('somelib.dart', show: ['foo', 'bar']); 260 #import('somelib.dart', show: ['foo', 'bar']);
261 {% endhighlight %} 261 {% endhighlight %}
262 262
263 Then you will *only* import the names foo and bar from somelib. This is go od if you are only using a small part of a library and want to make that clear. Conversely: 263 Then you will *only* import the names "foo" and "bar" from "somelib". This is go od if you are only using a small part of a library and want to make that clear. Conversely:
264 264
265 {% highlight dart %} 265 {% highlight dart %}
266 #import('somelib.dart', hide: ['foo', 'bar']); 266 #import('somelib.dart', hide: ['foo', 'bar']);
267 {% endhighlight %} 267 {% endhighlight %}
268 268
269 Here, you import every name except foo and bar. This is good for excluding t he one name that happens to cause a collision. 269 Here, you import every name except "foo" and "bar". This is good for excluding t he one name that happens to cause a collision.
270 270
271 ([Tracking issue #817](http://dartbug.com/817)) 271 ([Tracking issue #817](http://dartbug.com/817))
272 272
273 ## Re-export 273 ## Re-export
274 274
275 Let’s say you’re doing some refactoring and you decide to move a class from one library to another. But, you don’t want to break all of the code that assumes th at class is still in the old library. Ideally, you’d like code that imports *eit her* of those to be able to get to your class: you want it to appear to be in bo th places. 275 Let’s say you’re doing some refactoring and you decide to move a class from one library to another. But, you don’t want to break all of the code that assumes th at class is still in the old library. Ideally, you’d like code that imports *eit her* of those to be able to get to your class: you want it to appear to be in bo th places.
276 276
277 Or, let’s say you have a giant library with hundreds of names in it (we’ll call it dart:html). You want to split that up into a few smaller libraries. But you ’d also like users that want the whole kit and caboodle to just be able to impor t dart:html and get everything. 277 Or, let’s say you have a giant library with hundreds of names in it (we’ll call it "dart:html"). You want to split that up into a few smaller libraries. But you ’d also like users that want the whole kit and caboodle to just be able to impor t "dart:html" and get everything.
278 278
279 To fix this, Dart has re-exports. When you import a library, you can choose to also re-export the names you import from it. That will make it appear to code u sing *your* library that those names are coming directly from it. This lets you decouple the library where users get something from the library where it’s physi cally defined. For example: 279 To fix this, Dart has "re-exports". When you import a library, you can choose to also re-export the names you import from it. That will make it appear to code u sing *your* library that those names are coming directly from it. This lets you decouple the library where users get something from the library where it’s physi cally defined. For example:
280 280
281 {% highlight dart %} 281 {% highlight dart %}
282 // bar.dart 282 // bar.dart
283 someMethod() => print('hi!'); 283 someMethod() => print('hi!');
284 anotherMethod() => print('hello!'); 284 anotherMethod() => print('hello!');
285 285
286 // foo.dart 286 // foo.dart
287 #import('bar.dart', export: true); 287 #import('bar.dart', export: true);
288 {% endhighlight %} 288 {% endhighlight %}
289 289
290 Thanks to the `export: true` part here, any code that imports foo.dart will be able to access `someMethod()` and `anotherMethod()` as if they had been defined directly in foo.dart. You can use this in combination with selective imports to only re-export a subset of the names that an imported library defines. If we change the import in foo.dart to: 290 Thanks to the `export: true` part here, any code that imports "foo.dart" will be able to access `someMethod()` and `anotherMethod()` as if they had been defined directly in "foo.dart". You can use this in combination with selective imports to only re-export a subset of the names that an imported library defines. If we change the import in "foo.dart" to:
291 291
292 {% highlight dart %} 292 {% highlight dart %}
293 #import('bar.dart', show: ['someMethod'], export: true); 293 #import('bar.dart', show: ['someMethod'], export: true);
294 {% endhighlight %} 294 {% endhighlight %}
295 295
296 Then only `someMethod` will be re-exported. 296 Then only `someMethod` will be re-exported.
297 297
298 ([Tracking issue #760](http://dartbug.com/760)) 298 ([Tracking issue #760](http://dartbug.com/760))
299 299
300 ## Static methods are constants 300 ## Static methods are constants
(...skipping 13 matching lines...) Expand all
314 const Logger(this.logCallback(arg)); 314 const Logger(this.logCallback(arg));
315 } 315 }
316 {% endhighlight %} 316 {% endhighlight %}
317 317
318 ([Tracking issue #1652](http://dartbug.com/1652)) 318 ([Tracking issue #1652](http://dartbug.com/1652))
319 319
320 ## New catch syntax 320 ## New catch syntax
321 321
322 One strange consequence of marrying Dart’s optional type semantics with a Java-l ike syntax is that you end up with a syntax for `catch` clauses that *looks* lik e a type annotation, but is very much not like a type annotation in Dart: Dart t ype annotations have no runtime effects, but the type in a `catch` clause is use d at runtime to test against the thrown exception. 322 One strange consequence of marrying Dart’s optional type semantics with a Java-l ike syntax is that you end up with a syntax for `catch` clauses that *looks* lik e a type annotation, but is very much not like a type annotation in Dart: Dart t ype annotations have no runtime effects, but the type in a `catch` clause is use d at runtime to test against the thrown exception.
323 323
324 This causes some confusion and some nasty syntactic corner cases. For example, i f you just have `catch(foo)` does that mean catch an exception of any type and bind it to `foo` (which lines up with other parameters in Dart where the type a nnotation is optional), or does it mean catch an exception of type `foo` and do n’t bind it to a variable (which is what it would mean in Java)? 324 This causes some confusion and some nasty syntactic corner cases. For example, i f you just have `catch(foo)` does that mean "catch an exception of any type and bind it to `foo`" (which lines up with other parameters in Dart where the type a nnotation is optional), or does it mean "catch an exception of type `foo` and do n’t bind it to a variable" (which is what it would mean in Java)?
325 325
326 To avoid that, we decided that that syntax is invalid and you *must* do either ` catch(var foo)` or `catch(foo someVar)` to be clear about your intent. But that’ s definitely *not* the syntax for a parameter in Dart, so now users trip over *t hat.* 326 To avoid that, we decided that that syntax is invalid and you *must* do either ` catch(var foo)` or `catch(foo someVar)` to be clear about your intent. But that’ s definitely *not* the syntax for a parameter in Dart, so now users trip over *t hat.*
327 327
328 Our fix is to not try to follow Java-style syntax for this at all. Instead, Dart does: 328 Our fix is to not try to follow Java-style syntax for this at all. Instead, Dart does:
329 329
330 {% highlight dart %} 330 {% highlight dart %}
331 try { 331 try {
332 ... 332 ...
333 } on SomeException catch(ex) { ... } 333 } on SomeException catch(ex) { ... }
334 {% endhighlight %} 334 {% endhighlight %}
(...skipping 11 matching lines...) Expand all
346 {% endhighlight %} 346 {% endhighlight %}
347 347
348 This makes the syntax for defining them closer to how they are invoked. (You ca n of course have a curly block body too in addition to the simple lambda body sh own above.) 348 This makes the syntax for defining them closer to how they are invoked. (You ca n of course have a curly block body too in addition to the simple lambda body sh own above.)
349 349
350 Setters now have an `=` after their name, before the parameter list: 350 Setters now have an `=` after their name, before the parameter list:
351 351
352 {% highlight dart %} 352 {% highlight dart %}
353 set theAnswer=(int value) { print('The answer is now $value.'); } 353 set theAnswer=(int value) { print('The answer is now $value.'); }
354 {% endhighlight %} 354 {% endhighlight %}
355 355
356 When reflecting over a type (in the forthcoming mirrors system), the name of a s etter will include the “=”, so this makes the definition syntax reflect that. 356 When reflecting over a type (in the forthcoming mirrors system), the name of a s etter will include the "=", so this makes the definition syntax reflect that.
357 357
358 ([Tracking issue #3602](http://dartbug.com/3602)) 358 ([Tracking issue #3602](http://dartbug.com/3602))
359 359
360 ## Conclusion 360 ## Conclusion
361 361
362 There are a few other minor changes and clean-ups, but that’s the big noticeable stuff. As always, your feedback, questions and comments are welcome on the [mai ling list](http://dartlang.org/mailing-list) and our [issue tracker](http://dart bug.com). 362 There are a few other minor changes and clean-ups, but that’s the big noticeable stuff. As always, your feedback, questions and comments are welcome on the [mai ling list](http://dartlang.org/mailing-list) and our [issue tracker](http://dart bug.com).
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698