Skip to content

Commit

Permalink
Improved same method for IList, ISet and IMap.
Browse files Browse the repository at this point in the history
  • Loading branch information
marcglasberg committed Apr 1, 2024
1 parent 35ddd1b commit 00f0ba9
Show file tree
Hide file tree
Showing 9 changed files with 50 additions and 35 deletions.
2 changes: 1 addition & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
## 10.2.1
## 10.2.2

* You can now declare empty lists, sets and maps like
this (https://github.com/marcglasberg/fast_immutable_collections/pull/74):
Expand Down
15 changes: 9 additions & 6 deletions lib/src/ilist/ilist.dart
Original file line number Diff line number Diff line change
Expand Up @@ -23,8 +23,7 @@ class IListEmpty<T> // ignore: must_be_immutable
/// IMPORTANT: You must always use the `const` keyword.
/// It's always wrong to use an `IListEmpty()` which is not constant.
@literal
const IListEmpty._([this.config = const ConfigList()])
: super._gen();
const IListEmpty._([this.config = const ConfigList()]) : super._gen();

@override
final ConfigList config;
Expand Down Expand Up @@ -94,7 +93,7 @@ class IListEmpty<T> // ignore: must_be_immutable
@override
bool same(IList<T>? other) =>
(other != null) &&
(other is IListEmpty) &&
(other is IListEmpty || (other is IListConst && (other as IListConst)._list.isEmpty)) &&
(config == other.config);
}

Expand Down Expand Up @@ -152,8 +151,8 @@ class IListConst<T> // ignore: must_be_immutable
@override
bool same(IList<T>? other) =>
(other != null) &&
(other is IListConst) &&
identical(_list, (other as IListConst)._list) &&
(((other is IListConst) && identical(_list, (other as IListConst)._list)) ||
(((other is IListEmpty) && _list.isEmpty))) &&
(config == other.config);
}

Expand Down Expand Up @@ -674,10 +673,14 @@ abstract class IList<T> // ignore: must_be_immutable
(_hashCode != null && other._hashCode != null && _hashCode != other._hashCode);
}

/// Will return `true` only if the lists internals are the same instances
/// Will return `true` if the lists internals are the same instances
/// (comparing by identity). This will be fast even for very large lists,
/// since it doesn't compare each item.
///
/// May can also return `true` under some other situations where it's very
/// cheap to determine that the lists are equal even if the lists internals
/// are NOT the same.
///
/// Note: This is not the same as `identical(list1, list2)` since it doesn't
/// compare the lists themselves, but their internal state. Comparing the
/// internal state is better, because it will return `true` more often.
Expand Down
17 changes: 10 additions & 7 deletions lib/src/imap/imap.dart
Original file line number Diff line number Diff line change
Expand Up @@ -24,8 +24,7 @@ class IMapEmpty<K, V> // ignore: must_be_immutable
/// IMPORTANT: You must always use the `const` keyword.
/// It's always wrong to use an `IMapEmpty()` which is not constant.
@literal
const IMapEmpty._([this.config = const ConfigMap()])
: super._gen();
const IMapEmpty._([this.config = const ConfigMap()]) : super._gen();

@override
final ConfigMap config;
Expand Down Expand Up @@ -91,7 +90,7 @@ class IMapEmpty<K, V> // ignore: must_be_immutable
@override
bool same(IMap<K, V>? other) =>
(other != null) &&
(other is IMapEmpty) &&
(other is IMapEmpty || (other is IMapConst && (other as IMapConst)._map.isEmpty)) &&
(config == other.config);
}

Expand Down Expand Up @@ -149,8 +148,8 @@ class IMapConst<K, V> // ignore: must_be_immutable
@override
bool same(IMap<K, V>? other) =>
(other != null) &&
(other is IMapConst) &&
identical(_map, (other as IMapConst)._map) &&
(((other is IMapConst) && identical(_map, (other as IMapConst)._map)) ||
(((other is IMapEmpty) && _map.isEmpty))) &&
(config == other.config);
}

Expand Down Expand Up @@ -887,9 +886,13 @@ abstract class IMap<K, V> // ignore: must_be_immutable
(_hashCode != null && other._hashCode != null && _hashCode != other._hashCode);
}

/// Will return `true` only if the maps internals are the same instances
/// Will return `true` if the maps internals are the same instances
/// (comparing by identity). This will be fast even for very large maps,
/// since it doesn't compare each entry.
/// since it doesn't compare each entry.
///
/// May can also return `true` under some other situations where it's very
/// cheap to determine that the maps are equal even if the maps internals
/// are NOT the same.
///
/// Note: This is not the same as `identical(map1, map2)` since it doesn't
/// compare the maps themselves, but their internal state. Comparing the
Expand Down
4 changes: 2 additions & 2 deletions lib/src/imap_of_sets/imap_of_sets.dart
Original file line number Diff line number Diff line change
Expand Up @@ -644,7 +644,7 @@ class IMapOfSets<K, V> // ignore: must_be_immutable,
/// - If [isDeepEquals] configuration is `false`:
/// Will return `true` only if the maps internals are the same instances
/// (comparing by identity). This will be fast even for very large maps,
/// since it doesn't compare each entry.
/// since it doesn't compare each entry.
///
/// Note: This is not the same as `identical(map1, map2)` since it doesn't
/// compare the maps themselves, but their internal state. Comparing the
Expand Down Expand Up @@ -683,7 +683,7 @@ class IMapOfSets<K, V> // ignore: must_be_immutable,

/// Will return `true` only if the maps internals are the same instances
/// (comparing by identity). This will be fast even for very large maps,
/// since it doesn't compare each entry.
/// since it doesn't compare each entry.
///
/// Note: This is not the same as `identical(map1, map2)` since it doesn't
/// compare the maps themselves, but their internal state. Comparing the
Expand Down
15 changes: 9 additions & 6 deletions lib/src/iset/iset.dart
Original file line number Diff line number Diff line change
Expand Up @@ -23,8 +23,7 @@ class ISetEmpty<T> // ignore: must_be_immutable
/// IMPORTANT: You must always use the `const` keyword.
/// It's always wrong to use an `ISetEmpty()` which is not constant.
@literal
const ISetEmpty._([this.config = const ConfigSet()])
: super._gen();
const ISetEmpty._([this.config = const ConfigSet()]) : super._gen();

@override
final ConfigSet config;
Expand Down Expand Up @@ -90,7 +89,7 @@ class ISetEmpty<T> // ignore: must_be_immutable
@override
bool same(ISet<T>? other) =>
(other != null) &&
(other is ISetEmpty) &&
(other is ISetEmpty || (other is ISetConst && (other as ISetConst)._set.isEmpty)) &&
(config == other.config);
}

Expand Down Expand Up @@ -155,8 +154,8 @@ class ISetConst<T> // ignore: must_be_immutable
@override
bool same(ISet<T>? other) =>
(other != null) &&
(other is ISetConst) &&
identical(_set, (other as ISetConst)._set) &&
(((other is ISetConst) && identical(_set, (other as ISetConst)._set)) ||
(((other is ISetEmpty) && _set.isEmpty))) &&
(config == other.config);
}

Expand Down Expand Up @@ -611,10 +610,14 @@ abstract class ISet<T> // ignore: must_be_immutable
(_hashCode != null && other._hashCode != null && _hashCode != other._hashCode);
}

/// Will return `true` only if the sets internals are the same instances
/// Will return `true` if the sets internals are the same instances
/// (comparing by identity). This will be fast even for very large sets,
/// since it doesn't compare each item.
///
/// May can also return `true` under some other situations where it's very
/// cheap to determine that the sets are equal even if the sets internals
/// are NOT the same.
///
/// Note: This is not the same as `identical(set1, set2)` since it doesn't
/// compare the sets themselves, but their internal state. Comparing the
/// internal state is better, because it will return true more often.
Expand Down
2 changes: 1 addition & 1 deletion pubspec.yaml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
name: fast_immutable_collections
description: Immutable lists, sets, maps, and multimaps, which are as fast as their native mutable counterparts. Extension methods and comparators for native Dart collections.
version: 10.2.1
version: 10.2.2
homepage: https://github.com/marcglasberg/fast_immutable_collections
topics:
- collections
Expand Down
9 changes: 6 additions & 3 deletions test/ilist/ilist_empty_test.dart
Original file line number Diff line number Diff line change
Expand Up @@ -26,12 +26,12 @@ void main() {
// LAddAll
IList<String> list = const IList.empty();
list = list.addAll(["a", "b", "c"]);
list.forEach((_) { });
list.forEach((_) {});

// LAdd
list = const IList.empty();
list = list.add("d");
list.forEach((_) { });
list.forEach((_) {});
});

test("Make sure the internal list is List<int>, and not List<Never>", () {
Expand All @@ -50,6 +50,10 @@ void main() {

test(".same() is working properly", () {
expect(const IList.empty().same(const IList.empty()), isTrue);
expect(const IList.empty().same(const IList.empty()), isTrue);
expect(const IList.empty().same(const IListConst([])), isTrue);
expect(const IListConst([]).same(const IList.empty()), isTrue);
expect(const IListConst([]).hashCode, const IList.empty().hashCode);
});

test("equality", () {
Expand All @@ -62,7 +66,6 @@ void main() {
expect(const IList.empty().equalItems(const IList.empty()), isTrue);
expect(const IList.empty().equalItems(const IList.empty()), isTrue);


// equalItemsAndConfig
expect(IList(["a", "b"]).equalItemsAndConfig(const IList.empty()), isFalse);
expect(const IListConst(["a", "b"]).equalItemsAndConfig(const IList.empty()), isFalse);
Expand Down
17 changes: 8 additions & 9 deletions test/imap/imap_empty_test.dart
Original file line number Diff line number Diff line change
Expand Up @@ -25,22 +25,18 @@ void main() {
test("Make sure the IMapEmpty can be modified and later iterated", () {
// MAddAll
IMap<String, int> map = const IMap.empty();
map = map.addEntries([
const MapEntry("a", 1),
const MapEntry("b", 2),
const MapEntry("c", 3)
]);
map.forEach((_, __) { });
map = map.addEntries([const MapEntry("a", 1), const MapEntry("b", 2), const MapEntry("c", 3)]);
map.forEach((_, __) {});

// MAdd
map = const IMap.empty();
map = map.add("d", 4);
map.forEach((_, __) { });
map.forEach((_, __) {});

// MReplace
map = const IMap.empty();
map = map.add("d", 42);
map.forEach((_, __) { });
map.forEach((_, __) {});
});

test("Make sure the internal map is Map<int, String>, and not Map<Never>", () {
Expand All @@ -59,6 +55,10 @@ void main() {

test(".same() is working properly", () {
expect(const IMap.empty().same(const IMap.empty()), isTrue);
expect(const IMap.empty().same(const IMap.empty()), isTrue);
expect(const IMap.empty().same(const IMapConst({})), isTrue);
expect(const IMapConst({}).same(const IMap.empty()), isTrue);
expect(const IMapConst({}).hashCode, const IMap.empty().hashCode);
});

test("equality", () {
Expand All @@ -70,7 +70,6 @@ void main() {
expect(const IMapConst({}).equalItems(const IMap.empty().entries), isTrue);
expect(const IMap.empty().equalItems(const IMap.empty().entries), isTrue);


// equalItemsAndConfig
expect(IMap({1: "a", 2: "b"}).equalItemsAndConfig(const IMap.empty()), isFalse);
expect(const IMapConst({1: "a", 2: "b"}).equalItemsAndConfig(const IMap.empty()), isFalse);
Expand Down
4 changes: 4 additions & 0 deletions test/iset/iset_empty_test.dart
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,10 @@ void main() {

test(".same() is working properly", () {
expect(const ISet.empty().same(const ISet.empty()), isTrue);
expect(const ISet.empty().same(const ISet.empty()), isTrue);
expect(const ISet.empty().same(const ISetConst({})), isTrue);
expect(const ISetConst({}).same(const ISet.empty()), isTrue);
expect(const ISetConst({}).hashCode, const ISet.empty().hashCode);
});

test("equality", () {
Expand Down

0 comments on commit 00f0ba9

Please sign in to comment.