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

Unified Diff: GENERIC_METHODS.md

Issue 1586803002: Add file documenting generic method prototype syntax (Closed) Base URL: git@github.com:dart-lang/dev_compiler.git@master
Patch Set: Created 4 years, 11 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: GENERIC_METHODS.md
diff --git a/GENERIC_METHODS.md b/GENERIC_METHODS.md
new file mode 100644
index 0000000000000000000000000000000000000000..72b0e7f868b43fc779acc13d4e78fe894c00bf8b
--- /dev/null
+++ b/GENERIC_METHODS.md
@@ -0,0 +1,190 @@
+# Strong mode generic method prototype syntax
+
+This is a summary of the current (as of January 2016) supported comment-based
Bob Nystrom 2016/01/13 22:43:20 Nit: Remove "supported" since it's used later in t
Leaf 2016/01/14 00:28:54 Done.
+generic method syntax supported by the analyzer strong mode and the Dart Dev
+Compiler. The comment-based syntax essentially uses the proposed actual generic
+method syntax, but wraps it in comments. This allows developers to experiment
+with generic methods while still ensuring that their code runs on all platforms
+while generic methods are still being evaluated for inclusion into the language.
+
+## Declaring generic method parameters
+
+Generic method parameters are listed after the method or function name, inside
+of angle brackets and comments.
Bob Nystrom 2016/01/13 22:43:20 How about: "Generic method parameters are listed
Leaf 2016/01/14 00:28:54 Done.
+
+```dart
+// This declares a function which takes two unused generic method parameters
+int f/*<S, T>*/(int x) => 3;
+```
+
+As with classes, you can put bounds on type parameters.
+
+```dart
+// This declares a function which takes two unused generic method parameters
+// The first parameter (S) must extend num
+// The second parameter (T) must extend List<S>
+int f/*<S extends num, T extends List<S>>*/(int x) => 3;
+```
+
+Class methods (instance and static) can be declared to take generic parameters
+in the same way.
+
+```dart
+class C {
+ static int f/*<S, T>*/(int x) => 3;
+ int m/*<S, T>*/(int x) => 3;
+}
+```
+
+Function typed parameters, local functions, and function expressions can also be
+declared to take generic parameters.
+
+```dart
+// foo takes a generic method as a parameter
+void foo(int f/*<S>*/(int x)) {}
+
+// foo declares a local generic function
+void foo() {
+ int f/*<S>*/(int x) => 3;
+ return;
+}
+
+// foo binds a generic function expression to a local variable.
+void foo() {
+ var x = /*<S>*/(int x) => x;
+}
+```
+
+We do not currently support a way to declare a function as returning a generic
+function. This will eventually be supported using something analogous to Dart
+typedefs.
+
+## Using generic method parameters
+
+The previous examples declared generic method parameters, but did not use them.
+You can use a generic method parameter `T` anywhere that a type is expected in
+Dart by writing a type followed by `/*=T*/`. So for example, `dynamic /*=T*/`
+will be interpreted as `dynamic` by all non-strong mode tools, but will be
+interpreted as `T` by strong mode. In places where it is valid to leave off a
+type, simply writing `/*=T*/` will be interpreted as `dynamic` by non-strong
+mode tools, but will be interpreted as `T` by strong mode. For example:
+
+```dart
+// foo is a generic method which takes a single generic method parameter S.
+// In strong mode, the parameter x will have type S, and the return type will
+// be S
+// In normal mode, the parameter x will have type dynamic, and the return
+// type will be S.
+dynamic/*=S*/ foo/*<S>*/(dynamic/*=S*/ x) { return x; }
+```
+
+This can be written more concisely by leaving off the `dynamic`.
+
+```dart
+/*=S*/ foo/*<S>*/(/*=S*/ x) {return x;}
+```
+
+Note that the generic parameter is in scope in the return type of the function,
+in the argument list of the function, and in the body of the function. When
+declaring local variables and parameters, you can also use the `/*=T*/` syntax with `var`.
+
+```dart
+// foo is a generic method that takes a single generic parameter S, and a value
+// x of type S
+void foo/*<S>*/(var /*=S*/ x) {
+ // In strong mode, y will also have type S
+ var /*=S*/ y = x;
+
+ // In strong mode, z will also have type S
+ dynamic /*=S*/ z = y;
+}
+```
+
+Anywhere that a type literal is expected, you can also use the `/*=T*/` syntax to
+produce a type literal from the generic method parameter.
+
+```dart
+void foo/*<S>*/(/*=S*/ x) {
+ // In strong mode, s will get the type literal for S
+ Type s = dynamic /*=S*/;
Bob Nystrom 2016/01/13 22:43:20 Generic method type parameters are reified?
Jennifer Messerly 2016/01/13 22:49:33 In DDC, they will be, yes.
Leaf 2016/01/14 00:28:54 Just to be clear - the intention is that they will
+
+ // In strong mode, this attempts to cast 3 as type S
+ var y = (3 as dynamic /*=S*/);
+}
+```
+
+## Instantiating generic classes with generic method parameters
+
+You can use generic method parameters to instantiate generic classes using the
+same `/*=T*/` syntax.
+
+```dart
+// foo is a generic method which returns a List<S> in strong mode,
+// but which returns List<dynamic> in normal mode.
+List<dynamic /*=S*/> foo/*<S>*/(/*=S*/ x) {
+ // l0 is a list literal whose reified type will be List<S> in strong mode,
+ // and List<dynamic> in normal mode.
+ var l0 = <dynamic /*=S*/>[x];
+
+ // as above, but with a regular constructor.
+ var l1 = new List<dynamic /*=S*/>();
+ return l1;
+}
+```
+
+In most cases, the entire type argument list to the generic class can be
+enclosed in parentheses, eliminating the need for explicitly writing `dynamic`.
+
+```dart
+// This is another way of writing the same code as above
+List/*<S>*/ foo/*<S>*/(/*=S*/ x) {
+ // The shorthand syntax is not yet supported for list and map literals
Bob Nystrom 2016/01/13 22:43:20 Will this be fixed soon? If so, I wouldn't mention
Jennifer Messerly 2016/01/13 22:49:33 https://github.com/dart-lang/sdk/issues/25407. It'
Jennifer Messerly 2016/01/14 00:15:01 sent out a fix
+ var l0 = <dynamic /*=S*/>[x];
+
+ // but with regular constructors you can use it
+ var l1 = new List/*<S>*/();
+ return l1;
+}
+```
+
+## Instantiating generic methods
+
+Generic methods can be called without passing type arguments. Strong mode will
+attempt to infer the type arguments automatically. If it is unable to do so,
+then the type arguments will be filled in with whatever their declared bounds
+are (by default, `dynamic`).
+
+```dart
+class C {
+ /*=S*/ inferableFromArgument/*<S>*/(/*=S*/ x) { return null;}
+ /*=S*/ notInferable/*<S>*/(int x) { return null;}
+}
+
+void main() {
+ C c = new C();
+ // This line will produce a type error, because strong mode will infer
+ // `int` as the generic argument to fill in for S
+ String x = c.inferableFromArgument(3);
+
+ // This line will not produce a type error, because strong mode is unable
+ // to infer a type and will fill in the type argument with `dynamic`.
Bob Nystrom 2016/01/13 22:43:20 "no implicit dynamic" would yell here, I assume?
Jennifer Messerly 2016/01/13 22:49:33 Yup. Aside: we're currently in a funny place with
+ String y = c.notInferable(3);
+}
+```
+
+In the case that strong mode cannot infer the generic type arguments, the same
+syntax that was shown above for instantiating generic classes can be used to
+instantiate generic methods explicitly.
+
+```dart
+void main() {
+ C c = new C();
+ // This line will produce a type error, because strong mode will infer
+ // `int` as the generic argument to fill in for S
+ String x = c.inferableFromArgument(3);
+
+ // This line will produce a type error in strong mode, because `int` is
+ // explicitly passed in as the argument to use for S
+ String y = c.notInferable/*<int>*/(3);
+}
+```
« 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