Index: docs/newsletter/20170818.md |
diff --git a/docs/newsletter/20170818.md b/docs/newsletter/20170818.md |
new file mode 100644 |
index 0000000000000000000000000000000000000000..1db74634b551ea68600afa38ba2cdbbe5c2ca326 |
--- /dev/null |
+++ b/docs/newsletter/20170818.md |
@@ -0,0 +1,214 @@ |
+# Dart Language and Library Newsletter |
+2017-08-18 |
+@floitschG |
+ |
+Welcome to the Dart Language and Library Newsletter. |
+ |
+## If you missed it |
+Did you know that you can write trailing commas to arguments and parameters? This feature was added to the specification about a year ago. |
+ |
+It's main use-case is to unify parameter and argument lists that span multiple lines. For example, [Flutter] uses it extensively to keep tree-like instantiations nicely aligned: |
+ |
+[Flutter]: http://flutter.io |
+ |
+``` dart |
+ return new Material( |
+ // Column is a vertical, linear layout. |
+ child: new Column( |
+ children: <Widget>[ |
+ new MyAppBar( |
+ title: new Text( |
+ 'Example title', |
+ style: Theme.of(context).primaryTextTheme.title, |
+ ), |
+ ), |
+ new Expanded( |
+ child: new Center( |
+ child: new Text('Hello, world!'), |
+ ), |
+ ), |
+ ], |
+ ), |
+``` |
+ |
+Note how every argument list ends with a comma. The `dartfmt` tool knows about these trailing commas and ensures that the individual entries stay on their own lines so that it is easy to move them around with cut and paste. |
+ |
+Recently, we also updated the specification to allow trailing commas in `assert`s. This makes the syntax of `assert`s more consistent with function calls. |
+ |
+### Function Type Syntax |
+A few months ago, we added a new function type syntax to Dart (we mentioned it in our first newsletter). |
+ |
+``` dart |
+// Examples: |
+typedef F = void Function(int); // A void function that takes an int. |
+ |
+void foo(T Function<T>(T x) f) { // foo takes a generic function. |
+ ... |
+} |
+ |
+class A { |
+ // A has a field `f` of type function that takes a String and returns void. |
+ void Function(String) f; |
+} |
+``` |
+ |
+Before we added the new function-type syntaxes, we evaluated multiple options. In this section I will summarize some of the discussions we had. |
+ |
+#### Motivation |
+The new function-type syntax intends to solve three issues: |
+ |
+1. the old `typedef` syntax doesn't support generic types. |
+2. the old function syntax can't be used for fields and locals. |
+3. in the old syntax, providing only one identifier in an argument position is interpreted as name and not type. For example: `typedef f(int);` is *not* a typedef for a function that expects an `int`, but for a function that expects `dynamic` and names the argument "int". |
+ |
+With Dart 2.0 we will support generic methods, and also generic closures. This means that a function can accept a generic function as argument. We were lacking a way to express this type. |
+ |
+Dart 1.x has two ways to express function types: a) an inline syntax for parameters and b) `typedef`s. |
+ |
+It was easy to extend the inline syntax to support generic arguments: |
+ |
+ |
+``` dart |
+// Takes a function `factoryForA` that is generic on T. |
+void foo(A<T> factoryForA<T>()) { |
+ A<int> x = factoryForA<int>(); |
+ A<String> x = factoryForA<String>(); |
+} |
+``` |
+ |
+However, there was no easy way to do the same for `typedef`s: |
+ |
+``` dart |
+typedef A<T> FactoryForA<T>();// Does *not* do what we want it to do: |
+ |
+FactoryForA f; // A function that returns an `A<dynamic>`. |
+FactoryForA<String> f2; // A function that returns an `A<String>`. |
+f<int>(); // Error: `f` is not generic. |
+``` |
+ |
+We had already used the most consistent place for the generic method argument as a template argument to the `typedef` itself. If we could go back in time, we could change it as follows: |
+ |
+``` dart |
+typedef<T> List<T> TemplateTypedef(); |
+TemplateTypedef<int> f; // A function that returns a List<int>. |
+TemplateTypedef f; // A function that returns a List<dynamic>. |
+ |
+typedef List<T> GenericTypedef<T>(); |
+GenericTypedef f; // A function that is generic. |
+List<int> ints = f<int>(); |
+List<String> strings = f<String>(); |
+``` |
+ |
+Given that this would be a breaking change we explored alternatives that would also solve the other two issues. In particular the new syntax had to work for locals and fields, too. |
+ |
+First and foremost the new syntax had to be readable. It also had to solve the three mentioned issues. Finally, we wanted to make sure, we didn't choose a syntax that would hinder future evolution of the language. We made sure that the syntax would work with: |
+- nullability: the syntax must be nullable without too much hassle: |
+ ``` dart |
+ (int)->int?; // A function that is nullable, or that returns a nullable integer? |
+ Problem disappears with <- |
+ int <- (int)? ; vs int? <- (int) |
+ ``` |
+- union types (in case we ever want them). |
+ |
+ |
+#### Common Characteristics |
+For all the following proposals we had decided that the arguments could either be just the type, or optionally have a name. For example, `(int)->int` is equivalent to `(int id)->int`. Especially with multiple arguments of the same type, providing a name can make it much easier to reason about the type: `(int id, int priority) -> void`. However, type-wise these parameter names are ignored. |
+ |
+All of the proposals thus interpret single-argument identifiers as types. This is in contrast to the old syntax where a single identifier would state the name of the parameter: in `void foo(bar(int)) {...}` the `int` is the name of the parameter to `bar`. This discrepancy is hopefully temporary, as we intend to eventually change the behavior of the old syntax. |
+ |
+##### Right -> Arrow |
+Using `->` as function-type syntax feels very natural and is used in many other languages: Swift, F#, SML, OCaml, Haskell, Miranda, Coq, Kotlin, and Scala (with =>). |
+ |
+Examples: |
+``` dart |
+typedef F = (int) -> void; // Function from (int) to void. |
+typedef F<T> = () -> List<T>; // Template Typedef. |
+typedef F = <T>(T) -> List<T>; // Generic function from T to List<T>. |
+``` |
+ |
+We could even allow a short form when there is only one argument: `int->int`. |
+ |
+We have experimented with this syntax: [https://codereview.chromium.org/2439573003/] |
+ |
+Advantages: |
+- easy to learn and familiar to many developers. |
+- could support shorthand form `int->int`. |
+ |
+Open questions: |
+- support shorthand form? |
+- whitespace. Should it be `(int, int) -> String` or `(int, int)->String`, etc. |
+ |
+Disadvantages: |
+- Relatively late token. The parser would have to do relatively big lookaheads. |
+- Works badly with nullable types: |
+ ``` dart |
+ typedef F = (int) -> int?; // Nullable function or nullable int? |
+ // Could be disambiguated as follows: |
+ typedef F = ((int)->int)?; // Clearly nullable function. |
+ ``` |
+ |
+ |
+##### Left <- Arrow |
+This section explores using `<-` as function-type syntax. There is at least one other language that uses this syntax: [Twelf](http://www.cs.cmu.edu/~twelf/guide-1-2/twelf_3.html). |
+ |
+Examples: |
+``` dart |
+typedef F = void <- (int); // Function from (int) to void. |
+typedef F<T> = List<T> <- (); // Template Typedef. |
+typedef F = List<T> <- <T>(T); // Generic function from T to List<T>. |
+``` |
+ |
+Could also allow a short form: `int<-int`. (For some reason this seems to read less nicely than `int->int`.) |
+ |
+We have experimented with this syntax: [https://codereview.chromium.org/2466393002/] |
+ |
+Advantages: |
+- return value is on the left, similar to normal function signatures. This also simplifies `typedef`s, where the return value is more likely to stay on the first line. |
+- faster to parse, since the `<-` doesn't require a lot of look-ahead. |
+- relatively similar to `->`. |
+- no problems with nullable types: |
+ ``` dart |
+ typedef F = int <- (int)?; // Nullable function. |
+ typedef F = int? <- (int); // Returns nullable int. |
+ ``` |
+ |
+Open Questions: |
+- whitespace? |
+- support shorthand form? |
+ |
+Disadvantages: |
+- `<-` is ambiguous: `x<-y ? foo(x) : foo(y) // if x < (-y) ...`. |
+- Not as familiar as `->`. |
+ |
+##### Function |
+Dart already uses `Function` as general type for functions. It is relatively straightforward to extend the use of `Function` to include return and parameter types. (And no: it's not `Function<int, int>` since that wouldn't work for named arguments). |
+ |
+ |
+``` dart |
+typedef F = void Function(int); // Function from (int) to void. |
+typedef F<T> = List<T> Function(); // Template Typedef. |
+typedef F = List<T> Function<T>(T); // Generic function from T to List<T>. |
+``` |
+ |
+This form does not allow any shorthand syntax, but fits nicely into the existing parameter syntax. |
+ |
+Before we accepted this syntax, we had experimented with this syntax: [https://codereview.chromium.org/2482923002/] |
+ |
+Advantages: |
+- very similar to the syntax of the corresponding function declarations. |
+- no ambiguity. |
+- (almost) no new syntax. That is, the type can be immediately extrapolated from other syntax. |
+- no open questions wrt whitespace. |
+- symmetries with existing use of `Function`: |
+ ``` dart |
+ Function f; // a function. |
+ Function(int x) f; // a function that takes an int. |
+ double Function(int) f; // a function that takes an int and returns a double. |
+ ``` |
+ |
+Disadvantages: |
+- longer. |
+ |
+##### Conclusion |
+We found that the `Function`-based syntax fits nicely into Dart and fulfills all of our requirements. Due to its similarity to function declarations it is also very future-proof. Any feature that works with function declarations should work with the `Function`-type syntax, as well. |
+ |