Dart 1.19リリースノート

More than 1 year has passed since last update.

Dart 1.19がリリースされました。今回のStrong Mode周りの変更などはなかなか便利なので紹介していきます。


関連リンク


1.19 変更点


言語仕様の変更


最後の引数やパラーメータにカンマをつけることが可能に

関数宣言における最後のパラメーターや関数呼び出しにおける最後の引数のあとにtrailing commaをつけることが可能になりました。開発が楽になりますね。

void main() {

var test = new TestClass(
str1:"A",
str2:"B",
str3:"C",
str4:"D", // この行の最後のカンマがつけられるようになった
);
test.func2(); // ABCD
}

class TestClass {
String str1,str2,str3,str4;

TestClass({
this.str1,
this.str2,
this.str3,
this.str4, // この行もOK!
});
void func2(){
print(str1 + str2 + str3 + str4);
}
}

これは開発ブログに表示されていたgifを見るとさらにわかりやすいと思います。

img


画像元: Dart News & Updates: Dart 1.19: Improved developer experiences


関連Issue : Allow trailing commas in parameter and argument lists. · Issue #26644 · dart-lang/sdk


周辺ツールの変更点


dartfmt

上の言語仕様の変更にともなってtralling commas関連のフォーマットをサポートしました。そのほかにも改善されたようです。詳しくはdart_styleレポジトリのCHANGELOGを確認してください。


Pub

主要な変更を取り上げていきます。その他はCHANGELOGを確認してください。



  • --no-packages-dirフラグがpub getpub upgradepub downgradeに追加されました。このフラグをつけてコマンドを実行すると、pubはpackages/をせず、またもしある場合も削除してくれます。これは--no-package-symlinksフラグがサポートされなくなったものを埋め合わせるためのものです。

  • Flutter SDKのバージョンをpubspec.yamlの中で指定できるようになりました。


pubspec.yaml

environment:

flutter: ^0.1.2
sdk: >=1.19.0 <2.0.0


  • packageのdependenciesを指定する際に、sdkからそのpackageを取得するためのオプションsdkが追加されました。現在はflutterだけサポートされています。上の変更と合わせてflutter関連のためのようですね。


pubspec.yaml

dependencies:

flutter_driver:
sdk: flutter
version: ^0.0.1

関連Issue

* SDK dependencies · Issue #1431 · dart-lang/pub

* Flutter SDK constraint · Issue #1432 · dart-lang/pub


dart2js



  • dart2dart( = dart --output-type=dart)が削除されました。1.11からdeprecated だったのでそこまで影響はないと考えられます。


DartVMについて

DartVMをビルドするために、C++11をサポートするコンパイラが必要になりました。古いバージョンのLinuxディストリビューションを利用している場合は注意が必要です。GCC4.8以上が必要とのことです。clangやXCodeで使われているコンパイラでは問題なく動くことが確認されています。

参考 : Building · dart-lang/sdk Wiki


Strong Mode

AnalyzerのStrong Modeがさらに強力になりました。追加された機能を見てみましょう。


新機能


Disable implicit casts

これは名前のとおり暗黙のダウンキャストを許可しないオプションです。ダウンキャストとは、基底クラスから派生クラスへの型変換を指します。下のサンプルコードを確認してみてください1

void main(){

Base test = new Base();
Sub test2 = test; // disable implicit castsを有効にするとここでerrorに
print(test2.str2); // こういうエラーを事前に検知できる
}

class Base {
String str;
}
class Sub extends Base {
String str2;
}

使いたい場合は.analysis_optionsで指定するか、


.analysis_options

analyzer:

strong-mode:
implicit-casts: false

もしくはdartanalyzerで--no-implicit-casts を指定してください。

dartanalyzer --strong --no-implicit-casts ~.dart

公式ドキュメントもありますが、すこしサンプルがわかりづらかったのでこういう形にしました。


Disable implicit dynamic

これは暗黙のdynamicを禁止するものです。ドキュメントにのっているサンプルコードがわかりやすいです。

main() {

var x; // これはエラー
var i = 123; // これはintと推論できるのでOK
dynamic y; // これはdynamicで宣言しているのでOK!
}

ドキュメントに


This also affects: parameters, return types, fields, creating objects with generic type, generic functions/methods, and supertypes


とあるように、これは多くの場所で作用します。

// これもエラーになります。

f(x) => x + 42;
dynamic f(dynamic x) => x + 42; //OK!
int f(int x) => x + 42; // okay

// クラス内のメンバー変数にも作用
class C {
var f; // これはエラー
dynamic f; // OK!
}

main() {
var x = []; // 暗黙で List<dynamic> になっているのでだめ
var y = [42]; // OK!: List<int>
var z = <dynamic>[]; // OK!: List<dynamic>

T genericFn<T>() => null;
genericFn(); // 暗黙で genericFn<dynamic> になっているのでだめ
genericFn<dynamic>(); // OK
int x = genericFn(); // OK: 暗黙の genericFn<int>だということがわかる
}

// エラー
class C extends Iterable { /* ... */ }
// OK
class C extends Iterable<dynamic> { /* ... */ }

使いたい場合は.analysis_optionsで指定するか、


.analysis_options

analyzer:

strong-mode:
implicit-casts: false

もしくはdartanalyzerで--no-implicit-dynamicを指定してください。

dartanalyzer --strong --no-implicit-dynamic *.dart

上2つの機能はどちらも開発中のものです。フィードバック募集中とのことでもありますし、便利ですので使ってみてはいかがでしょうか。


Breaking Chanages


  • コンストラクタを呼び出すときの変数から推論をしてくれるようになりました。

var map = new Map<String, String>();

// infer: Map<String, String>
var otherMap = new Map.from(map);

関連Issue : infer constructor type arguments from values · Issue #25220 · dart-lang/sdk


  • ローカル関数の返り値を推論してくれるようになりました。

void main() {

// 返り値はintだと推論してくれる
f() { return 40; }
int y = f() + 2; // 型チェック
print(y);
}

関連Issue : infer local function return types · Issue #26414 · dart-lang/sdk


  • ジェネリック型のパラーメーターにおけるtype promotionを許可するようになりました。

void fn/*<T>*/(/*=T*/ object) {

if (object is String) {
// `object`はこのblockの中では`String`として扱われる
print(object.substring(1));
}
}

関連Issue : "is" checks aren't considered with generic-method types · Issue #26965 · dart-lang/sdk



  • Future.thenに関する推論が賢くなりました。.then/*<Future<SomeType>>*/が必要なくなりそうです。

// これも推論してくれる

Future<List<int>> t2 = f.then((_) => [3]);
// これもOK.
Future<int> t2 = f.then((_) => new Future.value(42));

関連Issue: Can strong mode inference for Future.then be improved? · Issue #25944 · dart-lang/sdk


  • async 関数に関する推論も賢くなりました。

void test() async {

List<int> x = await [4]; // これは今までも推論してくれていた
List<int> y = await new Future.value([4]); // 今はこっちも推論してくれる
}

関連Issue : Handle implicit future unions in downwards inference · Issue #25322 · dart-lang/sdk


  • Sideway castsが禁止されました。

関連Issue : Sideways casts should be disallowed · Issue #26120 · dart-lang/sdk

もろもろの変更を見ても、かなり快適にStrong Modeの恩恵をうけることができるようになっている印象を受けます。よい。


あとがき

一時期消えたなどと言われていたDartですが、ここのところはFlutterやAngular2、Googleの新OS「Fuchsia」への採用などのニュースで活気づいています。Dart 2.0のリリースなどもふくめて、Dart Summit 2016までいろいろな動きがありそうです。興味深いものがあったらまとめて行きたいと思います。