Skip to main content

Highlights from the TC52 meeting on Feb 24, 2015

At the last TC52 meeting on Feb 24, 2015, we discussed a number of additional language features for Dart - including async, tear-offs and null-aware operators.

Update on async

Gilad reported that the implementation had, unsurprisingly, exposed some subtleties in the spec that need to be considered.  Some small adjustments in the language specification may follow from this.

The virtual machine now implements the sync* mechanism.  The async* mechanism is coming along.  The dart2js implementation is complete with respect to the feature set, but it still needs to be debugged.

The development of the async features has given rise to some useful insights.  For instance, sync* creates a synchronous generator, handling all the boilerplate for lazy iteration.  However, the documentation of the library classes need an enhanced level of precision in order for this to work well with the language implementation and specification.  The connection arises because the language specification says that Iterable is implemented by sync* methods.  A conflict arises because Iterator and other classes are allowed to cache some values such as the length, but this is not applicable for sync* functions, and so the spec needs to restrict that.  Consequently, the library documentation has been revised.

An issue arises with “nested” empty iterables for yield*.  The idea is that yield* is used to merge the output from a subiterator into the output of a given iterator.  The wording in the language specification did not specify exactly what to do if that subiterator were empty, but the intention is that the subiterator should be processed normally and iteration should be continued from where it was before that subiterator was inserted.  Adjustments to the specification will be made to clarify this.

Several issues have come up in connection with async primitives:

One issue is whether a construct on the form await (throw x) can throw immediately, or “await always awaits” must prevail.

It was noted that the return type of async uses flatten to avoid nested future types, and also that this should not create any difficulties for the type analysis.

It is not obvious whether await-for loops should require a Stream as the source of the awaited data, or they should allow for non-Stream objects with the required features.  The question arises statically, where a type warning may or may not be given for a non-Stream.  The question arises dynamically where a non-Stream may cause a runtime type error.

Currently, the implementation performs such a check dynamically, even in production mode.  We quickly agreed that it is problematic to have a dynamic check without an accompanying static warning, and also that any such dynamic check should probably only be performed in checked mode.  It is not obvious how to resolve the overall issue, though.

Erik pointed out that there is an underlying principle for this kind of decision:  The language may allow for any object that responds to the requests made by the generated code, or it may enforce a nominal type such that only objects implementing Stream can be used.  The rationale for the former approach (let us call it the “pragmatic” approach) is to run everything that can plausibly be given a semantics, no matter whether or not it is aligned with the associated type structure.  The rationale for the latter approach (let us call it the “typeful” approach) is to support software correctness via explicit contractual obligations and expectations (as expressed by nominal types and supported by dartdoc comments etc.).  It is possible to use both a pragmatic approach and a typeful approach, both statically and dynamically, so all four combinations must be considered.

Dynamically, the pragmatic approach seems to be well aligned with many other decisions in the language design (it’s the “Darty” choice); but as Gilad mentioned, the code that actually implements the features which are used in this context is so subtle that ad-hoc alternative implementations to the ones in the standard library are very likely to be a steady source of stubborn bugs.  For the few highly sophisticated developers who insist on writing their own implementations of “something that works as a stream” it should be easy to add an implements Stream clause to their implementation, such that it works with the stricter, typeful approach.

Statically, the pragmatic approach may be seen as a mistake, especially in the (presumably, vast majority of) cases where a non-Stream is used by accident rather than by intention.  Conversely, if a static warning is given whenever a non-Stream is used in this context, it will cause frustration for the sophisticated developers who have carefully chosen to use a non-Stream.

In summary, we may have implicitly preferred the typeful approach statically and the pragmatic approach dynamically, but no explicit decision was made.

Another matter is that a decision on an underlying principle in this case naturally affects the treatment of similar constructs, including the standard for statement, where changes would obviously be much more difficult.

A quite different issue is the decision about whether yield in async* may suspend.  If a tight loop contains a yield, it may produce a large number of data items which are not being received quickly enough.  These situations create a need for more flexibility than that which is currently granted by the specification.

Finally, Gilad mentioned that there are some missing static warnings in relation to async*/sync*, and a few other small issues.

Update on “Dart Enhancement Proposal”

We are ready to launch the process, and several activities are already taking place.  The process is github-based (see  The idea is that DEP authors file an issue in this github repository which includes a link to the proposal itself, which is stored as a separate github repository.  The proposal repository may also contain other elements such as examples, implementation etc.  The committee will go over incoming proposals according to the flowchart.

TC52 has a royalty-free patent policy. Therefore, when a proposal is accepted by the DEP committee for processing by TC52, the original contributor of the DEP needs to sign the 'ECMA TC52 external contributor form'.

Update on language extensions

Two things are likely to be ready for the next version of the language specification: Generalized tear-offs, and null-aware operators.

For generalized tear-offs, the coverage and discussions at the previous meeting are still valid.  Now there is a complete proposal which is currently getting prepared for markdown presentation etc.  It can be found at  It is done in a way that should be identical to the way that an external contributor could submit a proposal, such that it also serves as a test of the procedure and the associated documents.

For null-aware operators, the information and discussions from the previous meeting are still valid.  In this case it is a very simple proposal, just syntactic sugar, but it comes at a low cost.

We briefly discussed a proposal from Erik to change the class Function to take one type argument which would be the return type of the function represented by the given instance.  This could enable the type Function<T> to be more useful than the current type Function, and it seems to be a benign change because all existing occurrences of Function would be reinterpreted to mean Function<dynamic>, which would have a backward compatible semantics.

We did not discuss configurable imports, union types, generic methods, closure tear-offs, improvements to Type Promotion, nor subtyping for function types.  In most cases this was because there is nothing new.  For function type subtyping it was because we need to consider changes to the runtime semantics of Dart very, very carefully before we commit to them.

Next meeting

The next TC52 meeting is on March 19th, 2015. Main topics expected are finalization of tear-offs and null-aware operators.


Popular posts from this blog

Const, Static, Final, Oh my!

Posted by Seth Ladd

(This is an "oldie but a goodie" post originally written by Bob Nystrom. It is being posted here as the explanations still ring true.)

Bob writes:

"static", "final", and "const" mean entirely distinct things in Dart:

"static" means a member is available on the class itself instead of on instances of the class. That's all it means, and it isn't used for anything else. static modifies *members*.

"final" means single-assignment: a final variable or field *must* have an initializer. Once assigned a value, a final variable's value cannot be changed. final modifies *variables*.

"const" has a meaning that's a bit more complex and subtle in Dart. const modifies *values*. You can use it when creating collections, like const [1, 2, 3], and when constructing objects (instead of new) like const Point(2, 3). Here, const means that the object's entire deep state can be determ…

The new AdWords UI uses Dart — we asked why

Google just announced a re-designed AdWords experience. In case you’re not familiar with AdWords: businesses use it to advertise on and partner websites. Advertising makes up majority of Google’s revenue, so when Google decides to completely redo the customer-facing front end to it, it’s a big deal. The Dart team is proud to say that this new front end is built with Dart and Angular 2. Whenever you asked us whether Google is ‘even using Dart for anything,’ this is what we had in mind but couldn’t say aloud. Until now. We asked Joshy Joseph, the primary technical lead on the project, some questions. Joshy is focusing on things like infrastructure, application latency and development velocity, so he’s the right person to ask about Dart.Q: What exactly did we launch on Monday?It’s a complete redesign of the AdWords customer experience that is rolling out slowly as a test to a small initial set of advertisers. The most noticeable thing is probably the Material Design look and f…

Dart 1.12 Released, with Null-Aware Operators and more

Dart 1.12.0 is now released! It contains the new null-aware operators language feature, and enhancements to pub, Observatory, dartdoc, and much more.

Null-aware operators

The new null-aware operators help you reduce the amount of code required to work with references that are potentially null. This feature is a collection of syntactic sugar for traversing (potentially null) object calls, conditionally setting a variable, and evaluating two (potentially null) expressions.

Click or tap the red Run button below to see them in action.


  if null operator. `expr1 ?? expr2` evaluates to `expr1` if not `null`, otherwise `expr2`.


  null-aware assignment. `v ??= expr` causes `v` to be assigned `expr` only if `v` is `null`.


  null-aware access. `x?.p` evaluates to `x.p` if `x` is not `null`, otherwise evaluates to `null`.


  null-aware method invocation. `x?.m()` invokes `m` only if `x` is not `null`.

Learn more about Dart's null-aware operators in our Language Tour.

.packages fi…