9
3

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

Dart の reduce は使わない方がいい

Posted at

Flutter を触っていて、 Javascript と同じように List の reduce を使おうとしたらハマったので、皆さんも気をつけましょう。

こちらの記事のコードは DartPad で試せます。
書いている時点のバージョンは Flutter 1.22.0-12.1.pre Dart SDK 2.9.3 です。

要約

  • Dart の reduce は要素が一つの場合、そのまま値を返す。
  • Dart の reduce は List の要素の型と結果の型が変わる場合は使えない。

Dart の reduce

ドキュメントはこちらになります。
早速実行してみましょう。

void main() {
  List<int> test = [6, 9, 13];
  print(test.reduce((acc, element) {
    return acc + element;
  }));
}

Console には 28 と表示されました。これぐらい単純ならちゃんと動きます。

ブラックジャックの例

ブラックジャックの得点計算を例にします。各カードの得点は以下のようになります。

  • 2~10 : 数字の点数
  • J,Q,K : 10点

(A の得点については本題と関係ないので省略)

では、 reduce を使って点数を計算します。

void main() {
  List<int> test = [6, 9, 13];
  print(test.reduce((acc, element) {
    if (element > 10) {
      return acc + 10;
    }
    return acc + element;
  }));
}

Console には 25 と表示されました。うまく動いていそうです。

ハマるケース

ではどんなケースでうまく動かないのか。それは K 一枚のケースです。

void main() {
  List<int> test = [13];
  print(test.reduce((acc, element) {
    if (element > 10) {
      return acc + 10;
    }
    return acc + element;
  }));
}

Console には 13 と表示されました。List の要素が一つの時はそのまま値を返すようです。

正しいやり方

この問題に対処するには List.fold を使います。ドキュメントはこちら

void main() {
  List<int> test = [13];
  print(test.fold<int>(0, (acc, element) {
    if (element > 10) {
      return acc + 10;
    }
    return acc + element;
  }));
}

Console には 10 と表示されました。

結論

実際、最初のケースのように reduce の内部で特別な処理をしなければ問題はないです。
しかし、メンテナンスを通して特別な処理が入ることも考えられるので、(個人的な意見ですが)一律で fold を使うようした方がいいです。

おまけ

reduce は List の要素の型と結果の型が変わる場合は型エラーになります。
以下の例では List の要素が int で結果の型が double になります。

void main() {
  List<int> test = [6, 9, 13];
  print(test.reduce((acc, element) {
    return acc + (element / 2); // 型エラー!
  }));
  print(test.fold<double>(0, (acc, element) {
    return acc + (element / 2); // エラーになりません
  }));
}
9
3
1

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
9
3

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?