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

Unified Diff: docs/newsletter/20170818.md

Issue 3001943002: Newsletter 2017-08-18. (Closed)
Patch Set: Created 3 years, 4 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 side-by-side diff with in-line comments
Download patch
« no previous file with comments | « no previous file | no next file » | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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.
+
« no previous file with comments | « no previous file | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698