Skip to content

Commit

Permalink
Add Iterable.empty constructor.
Browse files Browse the repository at this point in the history
Convenience constructor giving an easy/quick way to create an empty iterable.

R=sgjesse@google.com

Review URL: https://codereview.chromium.org//1152483002
  • Loading branch information
lrhn committed May 22, 2015
1 parent 36d3e0d commit dcf0286
Show file tree
Hide file tree
Showing 3 changed files with 84 additions and 1 deletion.
11 changes: 11 additions & 0 deletions sdk/lib/core/iterable.dart
Original file line number Diff line number Diff line change
Expand Up @@ -101,6 +101,17 @@ abstract class Iterable<E> {
return new _GeneratorIterable<E>(count, generator);
}

/**
* Creates an empty iterable.
*
* The empty iterable has no elements, and iterating it always stops
* immediately.
*
* An empty iterable can be used in places where you always that
* the iterable you would otherwise create is empty.
*/
const factory Iterable.empty() = EmptyIterable<E>;

/**
* Returns a new `Iterator` that allows iterating the elements of this
* `Iterable`.
Expand Down
2 changes: 1 addition & 1 deletion sdk/lib/internal/iterable.dart
Original file line number Diff line number Diff line change
Expand Up @@ -658,7 +658,7 @@ class SkipWhileIterator<E> extends Iterator<E> {
* The always empty [Iterable].
*/
class EmptyIterable<E> extends Iterable<E>
implements EfficientLengthIterable<E> {
implements EfficientLengthIterable<E> {
const EmptyIterable();

Iterator<E> get iterator => const EmptyIterator();
Expand Down
72 changes: 72 additions & 0 deletions tests/corelib/iterable_empty_test.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
// Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.

import "package:expect/expect.dart";

main() {
testEmpty(name, it, [depth = 2]) {
Expect.isTrue(it.isEmpty, name);
Expect.isFalse(it.isNotEmpty, name);
Expect.equals(0, it.length, name);
Expect.isFalse(it.contains(null), name);
Expect.isFalse(it.any((x)=>true), name);
Expect.isTrue(it.every((x)=>false), name);
Expect.throws(() => it.first, (e) => e is StateError, name);
Expect.throws(() => it.last, (e) => e is StateError, name);
Expect.throws(() => it.single, (e) => e is StateError, name);
Expect.throws(() => it.elementAt(0), (e) => e is RangeError, name);
Expect.throws(() => it.reduce((a, b) => a), (e) => e is StateError, name);
Expect.throws(() => it.singleWhere((_) => true),
(e) => e is StateError, name);
Expect.equals(42, it.fold(42, (a, b) => "not 42"), name);
Expect.equals(42, it.firstWhere((v) => true, orElse: () => 42), name);
Expect.equals(42, it.lastWhere((v) => true, orElse: () => 42), name);
Expect.equals("", it.join("separator"), name);
Expect.equals("()", it.toString(), name);
Expect.listEquals([], it.toList(), name);
Expect.listEquals([], it.toList(growable: false), name);
Expect.listEquals([], it.toList(growable: true), name);
Expect.equals(0, it.toSet().length, name);
// Doesn't throw:
it.forEach((v) => throw v);
for (var v in it) {
throw v;
}
// Check that returned iterables are also empty.
if (depth > 0) {
testEmpty("$name-map", it.map((x)=>x), depth - 1);
testEmpty("$name-where", it.where((x)=>true), depth - 1);
testEmpty("$name-expand", it.expand((x)=>[x]), depth - 1);
testEmpty("$name-skip", it.skip(1), depth - 1);
testEmpty("$name-take", it.take(2), depth - 1);
testEmpty("$name-skipWhile", it.skipWhile((v) => false), depth - 1);
testEmpty("$name-takeWhile", it.takeWhile((v) => true), depth - 1);
}
}

testType(name, it, [depth = 2]) {
Expect.isTrue(it is Iterable<int>, name);
Expect.isFalse(it is Iterable<String>, name);
if (depth > 0) {
testType("$name-where", it.where((_)=>true), depth - 1);
testType("$name-skip", it.skip(1), depth - 1);
testType("$name-take", it.take(1), depth - 1);
testType("$name-skipWhile", it.skipWhile((_)=>false), depth - 1);
testType("$name-takeWhile", it.takeWhile((_)=>true), depth - 1);
testType("$name-toList", it.toList(), depth - 1);
testType("$name-toList", it.toList(growable: false), depth - 1);
testType("$name-toList", it.toList(growable: true), depth - 1);
testType("$name-toSet", it.toSet(), depth - 1);
}
}

test(name, it) {
testEmpty(name, it);
testType(name, it);
}

test("const", const Iterable<int>.empty());
test("new", new Iterable<int>.empty());
}

0 comments on commit dcf0286

Please sign in to comment.