Upgrade to Pro — share decks privately, control downloads, hide ads and more …

FlutterKaigi Day1「Dart のこれから」

FlutterKaigi Day1「Dart のこれから」

2021 年、Dart 2.12 で Null safety がデフォルトで有効になり、とても快適に開発できるようになってきました。

Null safety 以降もさまざまな機能が追加され、Dart はまだまだ進化を続けています。

このセッションでは、近年の進化の振り返りを簡単にした後、Dart の進化プロセスの紹介をして、これから Dart がどんな進化をしていくのかをできる限り詳しく紹介します。

トーク内容
01 近年、どのような進化を遂げてきたか
02 Dart の進化プロセス
03 仕様化を進めている新機能
 ・Views on an object without a wrapper object
 ・Static Metaprogramming
 ・Sound declaration-site variance
 ・Patterns and related features
04 おわりに

対象者
・Dart の近年追加された機能について振り返りたい方
・Dart の進化プロセスに興味のある方
・Dart のこれからに興味のある方

おかやまん

November 16, 2022
Tweet

More Decks by おかやまん

Other Decks in Technology

Transcript

  1. Agenda
 01 近年、どのような進化を遂げてきたか 
 02 Dart の進化プロセス 
 03 仕様化を進めている新機能 
   ・Patterns and

    related features 
   ・Static Metaprogramming 
   ・Views on an object without a wrapper object 
   ・Sound declaration-site variance 
 04 おわりに

  2. Agenda
 01 近年、どのような進化を遂げてきたか 
 02 Dart の進化プロセス 
 03 仕様化を進めている新機能 
   ・Patterns and

    related features 
   ・Static Metaprogramming 
   ・Views on an object without a wrapper object 
   ・Sound declaration-site variance 
 04 おわりに

  3. bool isEmpty(String s) => s.length == 0; void main() {

    // Runtime error isEmpty(null); } Dart 2.12 - Null safety
 bool isEmpty(String s) => s.length == 0; void main() { // Compile-time error isEmpty(null); } 01 近年、どのような進化を遂げてきたか 
 https://github.com/dart-lang/sdk/blob/main/CHANGELOG.md#2120---2021-03-03 

  4. bool isEmpty(String s) => s.length == 0; void main() {

    // Runtime error isEmpty(null); } Dart 2.12 - Null safety
 bool isEmpty(String s) => s.length == 0; void main() { // Compile-time error isEmpty(null); } 01 近年、どのような進化を遂げてきたか 
 https://github.com/dart-lang/sdk/blob/main/CHANGELOG.md#2120---2021-03-03 

  5. class A { int x; A(this.x); A.fromString(String s) : x

    = int.parse(s); } void main() { final listOfInts = [1, 2, 3]; final listOfStrings = ["1", "2", "3"]; for(final a in listOfInts.map((x) => A(x))) { print(a.x); } for(final a in listOfStrings.map((x) => A.fromString(x))) { print(a.x); } } Dart 2.15 - Constructor tear-offs
 class A { int x; A(this.x); A.fromString(String s) : x = int.parse(s); } void main() { final listOfInts = [1, 2, 3]; final listOfStrings = ["1", "2", "3"]; for(final a in listOfInts.map(A.new)) { print(a.x); } for(final a in listOfStrings.map(A.fromString)) { print(a.x); } }
 01 近年、どのような進化を遂げてきたか 
 https://github.com/dart-lang/sdk/blob/main/CHANGELOG.md#2150---2021-12-08 

  6. class A { int x; A(this.x); A.fromString(String s) : x

    = int.parse(s); } void main() { final listOfInts = [1, 2, 3]; final listOfStrings = ["1", "2", "3"]; for(final a in listOfInts.map((x) => A(x))) { print(a.x); } for(final a in listOfStrings.map((x) => A.fromString(x))) { print(a.x); } } Dart 2.15 - Constructor tear-offs
 class A { int x; A(this.x); A.fromString(String s) : x = int.parse(s); } void main() { final listOfInts = [1, 2, 3]; final listOfStrings = ["1", "2", "3"]; for(final a in listOfInts.map(A.new)) { print(a.x); } for(final a in listOfStrings.map(A.fromString)) { print(a.x); } } 01 近年、どのような進化を遂げてきたか 
 https://github.com/dart-lang/sdk/blob/main/CHANGELOG.md#2150---2021-12-08 

  7. enum Status { success, failure } extension StatusToCode on Status

    { int get code { switch (this) { case Status.success: return 0; case Status.failure: return 1; } } } Dart 2.17 - Enhanced enums with members
 enum Status { success(0), failure(1); final int code; const Status(this.code); } 01 近年、どのような進化を遂げてきたか 
 https://github.com/dart-lang/sdk/blob/main/CHANGELOG.md#2170---2022-05-11 

  8. enum Status { success, failure } extension StatusToCode on Status

    { int get code { switch (this) { case Status.success: return 0; case Status.failure: return 1; } } } Dart 2.17 - Enhanced enums with members
 enum Status { success(0), failure(1); final int code; const Status(this.code); } 01 近年、どのような進化を遂げてきたか 
 https://github.com/dart-lang/sdk/blob/main/CHANGELOG.md#2170---2022-05-11 

  9. class CupertinoPage<T> extends Page<T> { const CupertinoPage({ required this.child, this.maintainState

    = true, this.title, this.fullscreenDialog = false, LocalKey? key, String? name, Object? arguments, String? restorationId, }) : super( key: key, name: name, arguments: arguments, restorationId: restorationId, ); // ... } Dart 2.17 - Super parameters
 class CupertinoPage<T> extends Page<T> { const CupertinoPage({ required this.child, this.maintainState = true, this.title, this.fullscreenDialog = false, super.key, super.name, super.arguments, super.restorationId, }); // ... } 01 近年、どのような進化を遂げてきたか 
 https://github.com/dart-lang/sdk/blob/main/CHANGELOG.md#2170---2022-05-11 

  10. class CupertinoPage<T> extends Page<T> { const CupertinoPage({ required this.child, this.maintainState

    = true, this.title, this.fullscreenDialog = false, LocalKey? key, String? name, Object? arguments, String? restorationId, }) : super( key: key, name: name, arguments: arguments, restorationId: restorationId, ); // ... } Dart 2.17 - Super parameters
 class CupertinoPage<T> extends Page<T> { const CupertinoPage({ required this.child, this.maintainState = true, this.title, this.fullscreenDialog = false, super.key, super.name, super.arguments, super.restorationId, }); // ... } 01 近年、どのような進化を遂げてきたか 
 https://github.com/dart-lang/sdk/blob/main/CHANGELOG.md#2170---2022-05-11 

  11. main() { test('A test description', () { // Very long

    function body here... }, skip: true); } Dart 2.17 - Named args everywhere
 main() { test(skip: true, 'A test description', () { // Very long function body here... }); } 01 近年、どのような進化を遂げてきたか 
 https://github.com/dart-lang/sdk/blob/main/CHANGELOG.md#2170---2022-05-11 

  12. main() { test('A test description', () { // Very long

    function body here... }, skip: true); } Dart 2.17 - Named args everywhere
 main() { test(skip: true, 'A test description', () { // Very long function body here... }); } 01 近年、どのような進化を遂げてきたか 
 https://github.com/dart-lang/sdk/blob/main/CHANGELOG.md#2170---2022-05-11 

  13. • Dart 2.18
 ◦ Enhanced type inference for generic invocations

    with function literals 
 • Dart 2.17
 ◦ Enhanced enums with members
 ◦ Super parameters
 ◦ Named args everywhere
 • Dart 2.15
 ◦ Constructor tear-offs
 ◦ Generic type literals
 ◦ Explicit generic method instantiations
 ◦ Generic instantiation of function objects
 • Dart 2.14
 ◦ Unsigned shift operator
 ◦ Removed some restrictions on type arguments
 • Dart 2.13
 ◦ Non-function type aliases
 • Dart 2.12
 ◦ Null safety
 01 近年、どのような進化を遂げてきたか 
 https://github.com/dart-lang/sdk/blob/main/CHANGELOG.md 

  14. Agenda
 01 近年、どのような進化を遂げてきたか 
 02 Dart の進化プロセス 
 03 仕様化を進めている新機能 
   ・Patterns and

    related features 
   ・Static Metaprogramming 
   ・Views on an object without a wrapper object 
   ・Sound declaration-site variance 
 04 おわりに

  15. Dart の言語チーム
 ※ 2020 年 6 月時点 
 leafpetersen 


    lrhn
 eernstg
 munificent
 natebosch
 jakemac53
 stereotype441 
 mit-mit
 02 Dart の進化プロセス 
 https://github.com/dart-lang/language/blob/master/README.md#dart-language-team 

  16. Agenda
 01 近年、どのような進化を遂げてきたか 
 02 Dart の進化プロセス 
 03 仕様化を進めている新機能 
   ・Patterns and

    related features 
   ・Static Metaprogramming 
   ・Views on an object without a wrapper object 
   ・Sound declaration-site variance 
 04 おわりに

  17. コンセプト
 • パターン
 • パターンマッチング
 • 網羅性
 • 分割代入
 •

    タプル
 • 代数的データ型
 • データクラス
 03 仕様化を進めている新機能 - Patterns and related features 

  18. Record 機能 - 提案の動機
 03 仕様化を進めている新機能 - Patterns and related features

    
 Future<String> getPersonName() async => 'John'; Future<int> getUnreadCount() async => 10; void main() async { // List<Object> final result = await Future.wait([ getPersonName(), getUnreadCount(), ]); final personName = result[0] as String; final unreadCount = result[1] as int; final lowOrHigh = unreadCount < 10 ? 'low' : 'high'; // John's unread count is high. print("$personName’s unread count is $lowOrHigh."); }
  19. Record 機能 - 提案の動機
 03 仕様化を進めている新機能 - Patterns and related features

    
 Future<String> getPersonName() async => 'John'; Future<int> getUnreadCount() async => 10; void main() async { // List<Object> final result = await Future.wait([ getPersonName(), getUnreadCount(), ]); final personName = result[0] as String; final unreadCount = result[1] as int; final lowOrHigh = unreadCount < 10 ? 'low' : 'high'; // John's unread count is high. print("$personName's unread count is $lowOrHigh."); }
  20. Record 機能 - 提案の動機
 03 仕様化を進めている新機能 - Patterns and related features

    
 Future<String> getPersonName() async => 'John'; Future<int> getUnreadCount() async => 10; void main() async { // List<Object> final result = await Future.wait([ getPersonName(), getUnreadCount(), ]); final personName = result[0] as String; final unreadCount = result[1] as int; final lowOrHigh = unreadCount < 10 ? 'low' : 'high'; // John's unread count is high. print("$personName's unread count is $lowOrHigh."); }
  21. Record 機能 - 概要
 03 仕様化を進めている新機能 - Patterns and related features

    
 var tuple = ("first", 2, true);
 var record = (number: 123, name: "Main", type: "Street"); var record = ("first", number: 123, 2, name: "Main", true, type: "Street");
  22. Record 機能 - 概要
 03 仕様化を進めている新機能 - Patterns and related features

    
 var record = (1, a: 2, 3, b: 4); print(record.$0); // Prints "1". print(record.a); // Prints "2". print(record.$1); // Prints "3". print(record.b); // Prints "4".
  23. Record 機能 - 概要
 03 仕様化を進めている新機能 - Patterns and related features

    
 var record = (1, a: 2, 3, b: 4); print(record.$0); // Prints "1". print(record.a); // Prints "2". print(record.$1); // Prints "3". print(record.b); // Prints "4".
  24. Record 機能 - 概要
 03 仕様化を進めている新機能 - Patterns and related features

    
 var record = (1, a: 2, 3, b: 4); print(record.$0); // Prints "1". print(record.a); // Prints "2". print(record.$1); // Prints "3". print(record.b); // Prints "4".
  25. Record 機能 - 概要
 03 仕様化を進めている新機能 - Patterns and related features

    
 var record = (1, a: 2, 3, b: 4); print(record.$0); // Prints "1". print(record.a); // Prints "2". print(record.$1); // Prints "3". print(record.b); // Prints "4".
  26. Record 機能 - 注釈
 03 仕様化を進めている新機能 - Patterns and related features

    
 (int, String name, bool) triple; ({int n, String s}) pair; (bool, num, {int n, String s}) quad;
  27. Record 機能 - 注釈
 03 仕様化を進めている新機能 - Patterns and related features

    
 (int, String name, bool) triple; ({int n, String s}) pair; (bool, num, {int n, String s}) quad;
  28. Record 機能 - 注釈
 03 仕様化を進めている新機能 - Patterns and related features

    
 (int, String name, bool) triple; ({int n, String s}) pair; (bool, num, {int n, String s}) quad;
  29. Record 機能 - 注釈
 03 仕様化を進めている新機能 - Patterns and related features

    
 (int, String name, bool) triple; ({int n, String s}) pair; (bool, num, {int n, String s}) quad;
  30. Record 機能 - 注釈
 03 仕様化を進めている新機能 - Patterns and related features

    
 (int, String name, bool) triple; ({int n, String s}) pair; (bool, num, {int n, String s}) quad;
  31. Record 機能 - toString()
 03 仕様化を進めている新機能 - Patterns and related features

    
 // デバッグビルド print((1, 2, 3).toString()); // "(1, 2, 3)". print((a: 'str', 'int').toString()); // "(a: str, int)".
  32. Record 機能 - 等価性
 03 仕様化を進めている新機能 - Patterns and related features

    
 var a = (x: 1, 2); var b = (2, x: 1); print(a == b); // true.
  33. Record 機能 - with()
 03 仕様化を進めている新機能 - Patterns and related features

    
 void main() { (int, int, {Color color}) x = (0, 1, color: Color.red); var x2 = x.with(7); // Just changes x[0]. var x3 = x.with(_, 3); // Just changes x[1]. var x4 = x.with(1: 3); // Also just changes x[1]. var x5 = x.with(color: Color.Blue); // Just changes x.color. }
  34. Pattern 機能 - 提案の動機
 03 仕様化を進めている新機能 - Patterns and related features

    
 void main() async { try { await fetchData(); } on SocketException { handleException(); } on TimeoutException { handleException(); } }
  35. Pattern 機能 - 提案の動機
 03 仕様化を進めている新機能 - Patterns and related features

    
 void main() async { try { await fetchData(); } on SocketException, TimeoutException { handleException(); } }
  36. Pattern 機能 - 概要
 03 仕様化を進めている新機能 - Patterns and related features

    
 パターンに関する基本的な考え方
 • パターンが値と一致するかどうかを判断するために、ある値に対してテストすること ができる
 • いくつかのパターンは、マッチした場合、マッチした値からデータを取り出すことに よって、マッチした値を再構築する
 • 変数パターンは、マッチした値または非構造化された値に新しい変数をバインドす る。変数は、パターンがマッチしたときにのみ到達可能なコード領域内にスコープさ れる

  37. Pattern 機能 - 概要
 03 仕様化を進めている新機能 - Patterns and related features

    
 種類 例 論理和 subpattern1 | subpattern2 論理積 subpattern1 & subpattern2 関連 == expression, < expression キャスト foo as String null チェック subpattern? null アサート subpattern! 定数 123, null, 'string', math.pi, SomeClass.constant, const Thing(1, 2), const (1 + 2) 変数 foo, var bar, String str, _, int _ 括弧付き (subpattern) List [subpattern1, subpattern2] Map {"key": subpattern1, someConst: subpattern2} Record (subpattern1, subpattern2), (x: subpattern1, y: subpattern2) 抽出 SomeClass(x: subpattern1, y: subpattern2) https://github.com/dart-lang/language/blob/master/working/0546-patterns/patterns-feature-specification.md 

  38. Pattern 機能 - 論理和パターン
 03 仕様化を進めている新機能 - Patterns and related features

    
 var isPrimary = switch (color) { case Color.red | Color.yellow | Color.blue => true; default => false; };
  39. Pattern 機能 - 論理和パターン
 03 仕様化を進めている新機能 - Patterns and related features

    
 var isPrimary = switch (color) { case Color.red | Color.yellow | Color.blue => true; default => false; };
  40. Pattern 機能 - 論理和パターン
 03 仕様化を進めている新機能 - Patterns and related features

    
 switch (shape) { case Square(size: var s) | Circle(size: var s) when s > 0: print('Non-empty symmetric shape'); case Square() | Circle(): print('Empty symmetric shape'); default: print('Asymmetric shape'); }
  41. Pattern 機能 - 論理和パターン
 03 仕様化を進めている新機能 - Patterns and related features

    
 switch (shape) { case Square(size: var s) | Circle(size: var s) when s > 0: print('Non-empty symmetric shape'); case Square() | Circle(): print('Empty symmetric shape'); default: print('Asymmetric shape'); }
  42. Pattern 機能 - 論理和パターン
 03 仕様化を進めている新機能 - Patterns and related features

    
 switch (list) { // Matches a two-element list whose first element is 'a' or 'b': case ['a' | 'b', var c]: }
  43. 網羅性チェック - 概要
 03 仕様化を進めている新機能 - Patterns and related features 


    • 網羅性
 
 
 • 到達可能性
 switch (b) { case true: print('yes'); case false: print('no'); }
 switch (b) { case true: print('yes'); case false: print('no'); case bool b: print('unreachable'); }

  44. マクロ - 提案の動機
 03 仕様化を進めている新機能 - Static Metaprogramming 
 @immutable class

    User { const User({ required this.name, required this.age, }); final String name; final int age; @override bool operator ==(Object other) => other is User && other.runtimeType == runtimeType && other.name == name && other.age == age; @override int get hashCode => Object.hash( runtimeType, name, age, ); @override String toString() => 'User(' 'name=$name, ' 'age=$age' ')'; User copy({ String? name, int? age, }) => User( name: name ?? this.name, age: age ?? this.age, ); }
  45. マクロ - 提案の動機
 03 仕様化を進めている新機能 - Static Metaprogramming 
 import 'package:freezed_annotation/freezed_annotation.dart';

    part 'user.freezed.dart'; @freezed class User with _$User { const factory User({ required String name, required int age, }) = _User; }
  46. マクロ - 概要
 03 仕様化を進めている新機能 - Static Metaprogramming 
 macro class

    DataClass implements ClassDeclarationsMacro, ClassDefinitionMacro { const DataClass(); @override Future<void> buildDeclarationsForClass( ClassDeclaration clazz, ClassMemberDeclarationBuilder context) async { await Future.wait([ const AutoConstructor().buildDeclarationsForClass(clazz, context), const CopyWith().buildDeclarationsForClass(clazz, context), const HashCode().buildDeclarationsForClass(clazz, context), const Equality().buildDeclarationsForClass(clazz, context), const ToString().buildDeclarationsForClass(clazz, context), ]); } @override Future<void> buildDefinitionForClass( ClassDeclaration clazz, ClassDefinitionBuilder builder) async { await Future.wait([ const HashCode().buildDefinitionForClass(clazz, builder), const Equality().buildDefinitionForClass(clazz, builder), const ToString().buildDefinitionForClass(clazz, builder), ]); } }
  47. マクロ - 概要
 03 仕様化を進めている新機能 - Static Metaprogramming 
 macro class

    DataClass implements ClassDeclarationsMacro, ClassDefinitionMacro { const DataClass(); @override Future<void> buildDeclarationsForClass( ClassDeclaration clazz, ClassMemberDeclarationBuilder context) async { await Future.wait([ const AutoConstructor().buildDeclarationsForClass(clazz, context), const CopyWith().buildDeclarationsForClass(clazz, context), const HashCode().buildDeclarationsForClass(clazz, context), const Equality().buildDeclarationsForClass(clazz, context), const ToString().buildDeclarationsForClass(clazz, context), ]); } @override Future<void> buildDefinitionForClass( ClassDeclaration clazz, ClassDefinitionBuilder builder) async { await Future.wait([ const HashCode().buildDefinitionForClass(clazz, builder), const Equality().buildDefinitionForClass(clazz, builder), const ToString().buildDefinitionForClass(clazz, builder), ]); } }
  48. Views on an object without a wrapper object
 03 仕様化を進めている新機能 -

    Views on an object without a wrapper object 
 https://github.com/dart-lang/language/projects/1 

  49. Views on an object without a wrapper object
 03 仕様化を進めている新機能 -

    Views on an object without a wrapper object 
 https://github.com/dart-lang/language/issues/1474 

  50. View - 提案の動機
 03 仕様化を進めている新機能 - Views on an object without

    a wrapper object 
 • 拡張メソッドのように、ラッパーオブジェクトなしで、ゼロコストで特定のオブジェクト を拡張したい
 • ラッピングすることで、不適切な操作を禁止したり、回帰的な処理をより便利かつ安 全に実装したりしたい

  51. View - 概要
 03 仕様化を進めている新機能 - Views on an object without

    a wrapper object 
 view class IdNumber(int i) { operator <(IdNumber other) => i < other.i; bool verify(Some parameters) => ...; }
  52. View - 概要
 03 仕様化を進めている新機能 - Views on an object without

    a wrapper object 
 view class IdNumber(int i) { operator <(IdNumber other) => i < other.i; bool verify(Some parameters) => ...; }
  53. View - 概要
 03 仕様化を進めている新機能 - Views on an object without

    a wrapper object 
 view class IdNumber(int i) { operator <(IdNumber other) => i < other.i; bool verify(Some parameters) => ...; }
  54. View - 概要
 03 仕様化を進めている新機能 - Views on an object without

    a wrapper object 
 view class IdNumber(int i) { operator <(IdNumber other) => i < other.i; bool verify(Some parameters) => ...; } void main() { int myUnsafeId = 42424242; var safeId = IdNumber(42424242); safeId + 10; // Compile-time error 10 + safeId; // Compile-time error myUnsafeId = safeId; // Compile-time error }
  55. View - 概要
 03 仕様化を進めている新機能 - Views on an object without

    a wrapper object 
 view class IdNumber(int i) { operator <(IdNumber other) => i < other.i; bool verify(Some parameters) => ...; } void main() { int myUnsafeId = 42424242; var safeId = IdNumber(42424242); safeId + 10; // Compile-time error 10 + safeId; // Compile-time error myUnsafeId = safeId; // Compile-time error }
  56. 提案の動機
 03 仕様化を進めている新機能 - Sound declaration-site variance 
 class Writer<T> {

    void write(T x) => print(x); } void main() { Writer<Object> objectWriter = Writer<int>(); // Runtime error objectWriter.write("I'm a string!"); }
  57. 提案の動機
 03 仕様化を進めている新機能 - Sound declaration-site variance 
 class Writer<T> {

    void write(T x) => print(x); } void main() { Writer<Object> objectWriter = Writer<int>(); // Runtime error objectWriter.write("I'm a string!"); }
  58. 概要
 03 仕様化を進めている新機能 - Sound declaration-site variance 
 class Writer<in T>

    { void write(T x) => print(x); } void main() { // Compile-time error Writer<Object> objectWriter = Writer<int>(); objectWriter.write("I'm a string!"); }
  59. 概要
 03 仕様化を進めている新機能 - Sound declaration-site variance 
 class Writer<in T>

    { void write(T x) => print(x); } void main() { // Compile-time error Writer<Object> objectWriter = Writer<int>(); objectWriter.write("I'm a string!"); }
  60. Agenda
 01 近年、どのような進化を遂げてきたか 
 02 Dart の進化プロセス 
 03 仕様化を進めている新機能 
   ・Patterns and

    related features 
   ・Static Metaprogramming 
   ・Views on an object without a wrapper object 
   ・Sound declaration-site variance 
 04 おわりに