Dart 1.9.1リリースノート

最初に言っておきます。

 **Dartは死んでません。ただの方針転換です**

これが負け惜しみでないことは以下のリリースノートを見てわかってもらえれば幸いです。

# 1.9.1リリース！
今朝、待望のDart1.9がリリースされました。リリースノートは[こちら](https://groups.google.com/a/dartlang.org/forum/#!topic/announce/5phqw_mraGA/discussion)

今回のアップデートはECMA標準に制定した仕様の実装が完遂された記念すべき内容です。具体的には

- async/awaitの正式サポート
- enumの正式サポート

が含まれています。その他にも多くの変更が盛り込まれているので1つずつ紹介します

# 言語仕様の変更
## async/awaitサポート
ついにasync/awaitが構文レベルでサポートされました。使用可能になった予約語は以下の6つです。

- async
- await
- sync*
- async*
- yield
- yield*

### Future & Stream : async, await
`async`と`await`はFuture APIとStream APIを簡単に記述するための構文です。`async`のマーキングをつけた関数の中で`await`を使うことが出来ます。

```dart
checkVersion() async {
  var version = await lookUpVersion();
  if (version == expectedVersion) {
    // Do something.
  } else {
    // Do something else.
  }
}
```

このコードは次のFuture APIをそのまま使ったものと同義です

```dart

checkVersion() {
  lookUpVersion().then((version){
    if (version == expectedVersion) {
      // Do something.
    } else {
      // Do something else.
    }
  });
}
```

ここで`lookUpVersion()`はFutureを返す関数ですが、その記述も`async`を使って簡潔に、まるで同期的なコードと同じように記述することができます。

```dart
String lookUpVersionSync() => '1.0.0';

Future<String> lookUpVersion() async => '1.0.0';
```

async/awaitを使った記述ではtry/catch文が簡潔になる利点があります。

async/awaitではFuture APIだけでなくStream APIもサポートしています。同期処理のfor文に`await`をつけることでブロック内部を非同期実行し、内部の処理は`Stream.listen`で処理されます。

```dart
main() async {
  ...
  await for (var request in requestServer) {
    handleRequest(request);
  }
  ...
}
```

## Generators : sync* async*, yield, yield*
Dart1.9からはジェネレータをサポートしました。サポートしたのは **同期的ジェネレータ**, **非同期的ジェネレータ** の2つです。

### sync*
`sync*`と`yield`を使うことで同期的に値を返すジェネレータを記述できます。

```dart
Iterable naturalsTo(n) sync* { 
  int k = 0; 
  while (k < n) yield k++; 
}
```

上記のコードは与えられた`n`までの列挙を返す関数ですが、Listを作って返すのではなく遅延実行を行います。これをfor文のソースとして用いることで内部で`moveNext()`が呼ばれるたびにyieldで中断した処理が再開されます。

### async*
非同期のジェネレータではStream型で値を返すことが出来ます。

```dart
Stream asynchronousNaturalsTo(n) async* { 
  int k = 0; 
  while (k < n) yield k++; 
}
```

### 再帰的ジェネレータ : yield*
与えられた整数nから1までカウントダウンしていく次の再帰を使ったジェネレータは計算量が多く、無駄の多い実装です

```dart
Iterable naturalsDownFrom(n) sync* { 
  if (n > 0) { 
     yield n; 
     for (int i in naturalsDownFrom(n-1)) { yield i; } 
  }
} 
```

これに対して用意された文が`yield*`、読み方は **yield-each** です。上記のコードを次のように書き換えます。

```dart
Iterable naturalsDownFrom(n) sync* { 
  if ( n > 0) { 
    yield n; 
    yield* naturalsDownFrom(n-1); 
 } 
} 
```

`yield*`に渡されたジェネレータが止まるまで受け取った値を呼び出し元にyieldと同じように返すことが出来ます。

# 周辺ツールの改善
## フォーマッターの改善
dartfmtが改善され、より人間が読みやすいコードに整形するようになりました。dartfmtについては[こちら](https://www.dartlang.org/tools/dartfmt/)で使い方や整形のサンプルを見ることが出来ます。

## Dart Analyzerの外部化 & IDE統合
Dartの分析ツール dartanalyzerがAnalysis Serverとして分離され、統合機能がIntelliJのプラグインやDart Editorに搭載されました。

## コード分析の改善

- IDEの外のプロセスで実行するようにした。
- 未使用の変数やメンバなど、多くのヒントをくれるようになった。

# コアライブラリの改善
## dart:async
### `Future.wait`にオプショナル引数`cleanUp(successValue)`追加
与えられたすべてのFutureが終わるまで待つ`Future.wait`に`cleanUp`引数が追加されました。イメージとしては`Future.wait`に対する`then`のようなものです。複数のFutureをまたいで用いられたリソースの開放などに使われることを想定しています。

### 新クラス:SynchronousStreamController
APIドキュメントは[こちら](https://api.dartlang.org/apidocs/channels/stable/dartdoc-viewer/dart:async.SynchronousStreamController)

基本的にこれまでのStreamControllerと変わらない使い方ですが、唯一の利点として追加操作のレイテンシが改善されています。しかしながら「イベントがlistenされている途中でaddしてはいけない」など、制限事項も多くサンプルコードもないので今のところは様子見しておきたいクラスです

## dart:collection
### SplayTreeSetに新しいコンストラクタ`from(iterable)`を追加
与えられた列挙を元にSplayTreeSetを作るコンストラクタが追加されました。

## dart:convert
### Utf8EncoderとUtf8Decoderの`convert`関数に`start`と`end`引数を追加
オプショナル引数として`start`と`end`が追加され、文字列を部分的にエンコード・デコードできるようになりました。

## dart:core
### 新エラー: RangeErrorの追加
APIリファレンスは[こちら](https://api.dartlang.org/apidocs/channels/stable/dartdoc-viewer/dart:core.RangeError)

数値の範囲に関する例外を表すRangeErrorクラスが追加され、そのチェックのためのヘルパーメソッドも追加されました。

* RangeError.checkNotNegative
* RangeError.checkValidIndex
* RangeError.checkValidRange
* RangeError.checkValueInInterval

## dart:io
### ファイルのロックに関する変更
Dartから開いたファイルに対するロックの制御が可能になりました。`file.lock`や`file.lockSync`関数が追加されています。

### HttpServerのbind,bindSecureにv6Only,shared引数の追加
`bool v6Only`引数はそのままIPv6だけ使うようになります。`bool shared`引数がtrueの時、同じプロセス上のDartサーバーにから同じアドレス・ポートへの追加のバインドが可能になる…と書かれているのですが、私にはネットワークのことがよくわからないので詳しい方がいたらコメントで教えてください。

### Process.startにmode引数を追加
`Process.start`に`ProcessStartMode mode`引数が追加されました。開始モードの種類は`NORMAL`と`DETACHED`の2つです。`DETACHED`で開始されたプロセスは親（起動元）のプロセスと完全に切り離され、親プロセスが終了しても独立して動き続けます。また、stdinやstdout、stderr等を取得することも不可能になり、DETACHEDなプロセスから得られる情報はそのプロセスのpidだけです。

### Process.killPidの追加
上記のDETACHEDモードに関連してpidからプロセスを殺す`Process.killPid`関数が追加されました。

### ServerSocketへのshared引数の追加
先述のHttpServerと同様と思われるshared引数がServerSocket.bind、RawServerSocket.bind、SecureServerSocket.bind、RawSecureServerSocket.bindにも追加されています。

### SocketReferenceが非推奨に
もともとexperimentalのクラスだったので特に影響はないかと思います

### SocketとRawSocketのconnectにsourceAddress引数を追加
SocketクラスとRawSocketクラスのstatic関数`connect`に`sourceAddress`引数が追加されました。

### StdoutにnonBlockingプロパティを追加
Stdoutクラスに`nonBlocking`プロパティが追加されました。通常Stdoutクラスが提供するIOSinkは書き始めから書き終わりまでブロックされますが、`Stdout.nonBlocking`で渡されるIOSinkはブロックされません。

## dart:isolate
### Isolate.currentの追加
「ようやくか！」という機能ですが、そのコードが実行されているIsolateを取得できます。

### Isolate APIの拡張
Isolate周りが一気に便利になりました。追加されたメソッドは以下の5つです

* addOnExitListener
* removeOnExitListener
* setErrorsFatal
* addOnErrorListener
* removeOnErrorListener

また、`spawn`の第1引数の`entryPoint`に`message`引数を渡すことができるようになりました。渡される値は第2引数の`message`に与えます。

さらに、DartVMでIsolate APIを完全に実装し終えたということで、サーバーサイドDartのマルチコアでの平行化が可能となったようです。

>The Isolate API has now been fully implemented in the Dart VM, making it much easier to create applications that target multiple CPUs.

# まとめ
Dart1.9でECMA標準にある仕様はすべて実装を終えたということで、Dartは一旦小休止だと思います。今はGithubの方で次のECMA標準 3rd Editionの設計が進んでいるようです。それが固まり次第また次のゴールに向かってアップデートが重ねられていくと思います。

そういう意味では今こそがDartを学び始めるにふさわしいタイミングなのではないかと思います。先日DartVMをChromeに搭載しないことを決定したとのアナウンスがあり、そこそこのDart情報アンテナを張っていると自負している自分でも寝耳に水でした。Chrome上でネイティブにDartを動かすのは夢でしたがそれ以前にDartは書いていて楽しい言語です。「ブラウザでちゃんと動くJavaScriptを吐き出すことができる汎用言語」として発展していく道を選んだということはそれまで夢に費やしていた労力を現実に割り振ってくれるということだと信じていますので、今後は特にdart2jsの改善に力を入れてほしいと願っています。

ところで4月の終わりにGoogle本社で記念すべき第一回のDart Developers Summitが開催されます。( https://www.dartlang.org/events/2015/summit/ )。残念ながら現地にはいけないので中継と録画から情報をまとめたいと思っています。その一ヶ月後の5月にはGoogle I/O 2015も開催されますので、そこでの新情報にも期待しましょう。

以上。