diff --git a/src/async/impl.ts b/src/async/impl.ts index f7022f6..ee85c95 100644 --- a/src/async/impl.ts +++ b/src/async/impl.ts @@ -1,8 +1,8 @@ import { Collector } from "../collector/types.js"; import { asAsyncComparer, combineNullableAsyncComparers, createAsyncComparerUsing, defaultAsyncComparer } from "../comparer/async.js"; import { MaybeAsyncComparisonOrComparer, AsyncComparer } from "../comparer/types.js"; -import { strictEquals } from "../equality-comparer/sync.js"; -import { MaybeAsyncEqualityComparison } from "../equality-comparer/types.js"; +import { asAsyncEqualityComparer, defaultAsyncEqualityComparer } from "../equality-comparer/async.js"; +import { AsyncEqualityComparer, MaybeAsyncEqualityComparisonOrComparer } from "../equality-comparer/types.js"; import { createAsyncEqualityMap } from "../equality-map/index.js"; import { createAsyncEqualitySet } from "../equality-set/index.js"; import { createQueue } from "../queue.js"; @@ -42,31 +42,29 @@ export abstract class BaseAsyncSequence extends AsyncSequenceMarker im return new WhereAsyncSequence(this, predicate); } - groupBy(keySelector: MaybeAsyncConverter, elementSelector?: undefined, keyComparer?: MaybeAsyncEqualityComparison | undefined): AsyncSequence>; - groupBy(keySelector: MaybeAsyncConverter, elementSelector: MaybeAsyncConverter, keyComparer?: MaybeAsyncEqualityComparison | undefined): AsyncSequence>; + groupBy(keySelector: MaybeAsyncConverter, elementSelector?: undefined, keyComparer?: MaybeAsyncEqualityComparisonOrComparer | undefined): AsyncSequence>; + groupBy(keySelector: MaybeAsyncConverter, elementSelector: MaybeAsyncConverter, keyComparer?: MaybeAsyncEqualityComparisonOrComparer | undefined): AsyncSequence>; groupBy(keySelector: any, elementSelector?: any, keyComparer?: any) { return new GroupByAsyncSequence(this, keySelector, elementSelector, keyComparer); } - join(sequence: MaybeAsyncIterable, firstKeySelector: MaybeAsyncConverter, secondKeySelector: MaybeAsyncConverter, resultSelector?: undefined, keyComparer?: MaybeAsyncEqualityComparison | undefined): AsyncSequence<[TElement, TOther]>; - join(sequence: MaybeAsyncIterable, firstKeySelector: MaybeAsyncConverter, secondKeySelector: MaybeAsyncConverter, resultSelector: MaybeAsyncBiConverter, keyComparer?: MaybeAsyncEqualityComparison | undefined): AsyncSequence; + join(sequence: MaybeAsyncIterable, firstKeySelector: MaybeAsyncConverter, secondKeySelector: MaybeAsyncConverter, resultSelector?: undefined, keyComparer?: MaybeAsyncEqualityComparisonOrComparer | undefined): AsyncSequence<[TElement, TOther]>; + join(sequence: MaybeAsyncIterable, firstKeySelector: MaybeAsyncConverter, secondKeySelector: MaybeAsyncConverter, resultSelector: MaybeAsyncBiConverter, keyComparer?: MaybeAsyncEqualityComparisonOrComparer | undefined): AsyncSequence; join(sequence: any, firstKeySelector: any, secondKeySelector: any, resultSelector?: any, keyComparer?: any) { return new JoinAsyncSequence(this, wrap(sequence), firstKeySelector, secondKeySelector, resultSelector, keyComparer); } - groupJoin(sequence: MaybeAsyncIterable, firstKeySelector: MaybeAsyncConverter, secondKeySelector: MaybeAsyncConverter, resultSelector?: undefined, keyComparer?: MaybeAsyncEqualityComparison | undefined): AsyncSequence>; - groupJoin(sequence: MaybeAsyncIterable, firstKeySelector: MaybeAsyncConverter, secondKeySelector: MaybeAsyncConverter, resultSelector: MaybeAsyncBiConverter, TResult>, keyComparer?: MaybeAsyncEqualityComparison | undefined): AsyncSequence; + groupJoin(sequence: MaybeAsyncIterable, firstKeySelector: MaybeAsyncConverter, secondKeySelector: MaybeAsyncConverter, resultSelector?: undefined, keyComparer?: MaybeAsyncEqualityComparisonOrComparer | undefined): AsyncSequence>; + groupJoin(sequence: MaybeAsyncIterable, firstKeySelector: MaybeAsyncConverter, secondKeySelector: MaybeAsyncConverter, resultSelector: MaybeAsyncBiConverter, TResult>, keyComparer?: MaybeAsyncEqualityComparisonOrComparer | undefined): AsyncSequence; groupJoin(sequence: any, firstKeySelector: any, secondKeySelector: any, resultSelector?: any, keyComparer?: any) { return new GroupJoinAsyncSequence(this, wrap(sequence), firstKeySelector, secondKeySelector, resultSelector, keyComparer); } - async contains(obj: TElement, equater?: MaybeAsyncEqualityComparison) { - if (!equater) { - equater = strictEquals; - } + async contains(obj: TElement, equater?: MaybeAsyncEqualityComparisonOrComparer) { + equater = equater ? asAsyncEqualityComparer(equater) : defaultAsyncEqualityComparer; for await (const element of this) { - if (await equater(element, obj)) { + if (await equater.equals(element, obj)) { return true; } } @@ -74,7 +72,7 @@ export abstract class BaseAsyncSequence extends AsyncSequenceMarker im return false; } - async sequenceEquals(sequence: MaybeAsyncIterable, equater?: MaybeAsyncEqualityComparison) { + async sequenceEquals(sequence: MaybeAsyncIterable, equater?: MaybeAsyncEqualityComparisonOrComparer) { if (this === sequence) { return true; } @@ -88,9 +86,7 @@ export abstract class BaseAsyncSequence extends AsyncSequenceMarker im return false; } - if (!equater) { - equater = strictEquals; - } + equater = equater ? asAsyncEqualityComparer(equater) : defaultAsyncEqualityComparer; const thisIterator = this.iterator(); const thatIterator = that.iterator(); @@ -107,7 +103,7 @@ export abstract class BaseAsyncSequence extends AsyncSequenceMarker im return false; } - if (!await equater(thisNext.value, thatNext.value)) { + if (!await equater.equals(thisNext.value, thatNext.value)) { return false; } } @@ -121,7 +117,7 @@ export abstract class BaseAsyncSequence extends AsyncSequenceMarker im return new PrependAsyncSequence(this, obj); } - remove(obj: TElement, all?: boolean, equater?: MaybeAsyncEqualityComparison): AsyncSequence { + remove(obj: TElement, all?: boolean, equater?: MaybeAsyncEqualityComparisonOrComparer): AsyncSequence { return new RemoveAsyncSequence(this, obj, all, equater); } @@ -518,27 +514,27 @@ export abstract class BaseAsyncSequence extends AsyncSequenceMarker im return new OrderByAsyncSequence(this, true, selector, comparer); } - partition(equater?: MaybeAsyncEqualityComparison): AsyncSequence> { + partition(equater?: MaybeAsyncEqualityComparisonOrComparer): AsyncSequence> { return new PartitionAsyncSequence(this, equater); } - partitionBy(selector: MaybeAsyncConverter, equater?: MaybeAsyncEqualityComparison): AsyncSequence> { + partitionBy(selector: MaybeAsyncConverter, equater?: MaybeAsyncEqualityComparisonOrComparer): AsyncSequence> { return new PartitionByAsyncSequence(this, selector, equater); } - distinct(equater?: MaybeAsyncEqualityComparison): AsyncSequence { + distinct(equater?: MaybeAsyncEqualityComparisonOrComparer): AsyncSequence { return new DistinctAsyncSequence(this, equater); } - distinctBy(selector: MaybeAsyncConverter, equater?: MaybeAsyncEqualityComparison): AsyncSequence { + distinctBy(selector: MaybeAsyncConverter, equater?: MaybeAsyncEqualityComparisonOrComparer): AsyncSequence { return new DistinctByAsyncSequence(this, selector, equater); } - union(sequence: MaybeAsyncIterable, equater?: MaybeAsyncEqualityComparison): AsyncSequence { + union(sequence: MaybeAsyncIterable, equater?: MaybeAsyncEqualityComparisonOrComparer): AsyncSequence { return new UnionAsyncSequence(this, wrap(sequence), equater); } - unionBy(sequence: MaybeAsyncIterable, selector: MaybeAsyncConverter, equater?: MaybeAsyncEqualityComparison): AsyncSequence { + unionBy(sequence: MaybeAsyncIterable, selector: MaybeAsyncConverter, equater?: MaybeAsyncEqualityComparisonOrComparer): AsyncSequence { return new UnionByAsyncSequence(this, wrap(sequence), selector, equater); } @@ -813,29 +809,29 @@ export class DelegatedAsyncSequence extends AsyncSequenceMarker implem return this.#sequence.where(predicate); } - groupBy(keySelector: MaybeAsyncConverter, elementSelector?: undefined, keyComparer?: MaybeAsyncEqualityComparison | undefined): AsyncSequence>; - groupBy(keySelector: MaybeAsyncConverter, elementSelector: MaybeAsyncConverter, keyComparer?: MaybeAsyncEqualityComparison | undefined): AsyncSequence>; + groupBy(keySelector: MaybeAsyncConverter, elementSelector?: undefined, keyComparer?: MaybeAsyncEqualityComparisonOrComparer | undefined): AsyncSequence>; + groupBy(keySelector: MaybeAsyncConverter, elementSelector: MaybeAsyncConverter, keyComparer?: MaybeAsyncEqualityComparisonOrComparer | undefined): AsyncSequence>; groupBy(keySelector: any, elementSelector?: any, keyComparer?: any) { return this.#sequence.groupBy(keySelector, elementSelector, keyComparer); } - join(sequence: MaybeAsyncIterable, firstKeySelector: MaybeAsyncConverter, secondKeySelector: MaybeAsyncConverter, resultSelector?: undefined, keyComparer?: MaybeAsyncEqualityComparison | undefined): AsyncSequence<[TElement, TOther]>; - join(sequence: MaybeAsyncIterable, firstKeySelector: MaybeAsyncConverter, secondKeySelector: MaybeAsyncConverter, resultSelector: MaybeAsyncBiConverter, keyComparer?: MaybeAsyncEqualityComparison | undefined): AsyncSequence; + join(sequence: MaybeAsyncIterable, firstKeySelector: MaybeAsyncConverter, secondKeySelector: MaybeAsyncConverter, resultSelector?: undefined, keyComparer?: MaybeAsyncEqualityComparisonOrComparer | undefined): AsyncSequence<[TElement, TOther]>; + join(sequence: MaybeAsyncIterable, firstKeySelector: MaybeAsyncConverter, secondKeySelector: MaybeAsyncConverter, resultSelector: MaybeAsyncBiConverter, keyComparer?: MaybeAsyncEqualityComparisonOrComparer | undefined): AsyncSequence; join(sequence: any, firstKeySelector: any, secondKeySelector: any, resultSelector?: any, keyComparer?: any) { return this.#sequence.join(sequence, firstKeySelector, secondKeySelector, resultSelector, keyComparer); } - groupJoin(sequence: MaybeAsyncIterable, firstKeySelector: MaybeAsyncConverter, secondKeySelector: MaybeAsyncConverter, resultSelector?: undefined, keyComparer?: MaybeAsyncEqualityComparison | undefined): AsyncSequence>; - groupJoin(sequence: MaybeAsyncIterable, firstKeySelector: MaybeAsyncConverter, secondKeySelector: MaybeAsyncConverter, resultSelector: MaybeAsyncBiConverter, TResult>, keyComparer?: MaybeAsyncEqualityComparison | undefined): AsyncSequence; + groupJoin(sequence: MaybeAsyncIterable, firstKeySelector: MaybeAsyncConverter, secondKeySelector: MaybeAsyncConverter, resultSelector?: undefined, keyComparer?: MaybeAsyncEqualityComparisonOrComparer | undefined): AsyncSequence>; + groupJoin(sequence: MaybeAsyncIterable, firstKeySelector: MaybeAsyncConverter, secondKeySelector: MaybeAsyncConverter, resultSelector: MaybeAsyncBiConverter, TResult>, keyComparer?: MaybeAsyncEqualityComparisonOrComparer | undefined): AsyncSequence; groupJoin(sequence: any, firstKeySelector: any, secondKeySelector: any, resultSelector?: any, keyComparer?: any) { return this.#sequence.groupJoin(sequence, firstKeySelector, secondKeySelector, resultSelector, keyComparer); } - contains(obj: TElement, equater?: MaybeAsyncEqualityComparison | undefined): Promise { + contains(obj: TElement, equater?: MaybeAsyncEqualityComparisonOrComparer | undefined): Promise { return this.#sequence.contains(obj, equater); } - sequenceEquals(sequence: MaybeAsyncIterable, equater?: MaybeAsyncEqualityComparison | undefined): Promise { + sequenceEquals(sequence: MaybeAsyncIterable, equater?: MaybeAsyncEqualityComparisonOrComparer | undefined): Promise { return this.#sequence.sequenceEquals(sequence, equater); } @@ -847,7 +843,7 @@ export class DelegatedAsyncSequence extends AsyncSequenceMarker implem return this.#sequence.prepend(obj); } - remove(obj: TElement, all?: boolean | undefined, equater?: MaybeAsyncEqualityComparison | undefined): AsyncSequence { + remove(obj: TElement, all?: boolean | undefined, equater?: MaybeAsyncEqualityComparisonOrComparer | undefined): AsyncSequence { return this.#sequence.remove(obj, all, equater); } @@ -934,43 +930,43 @@ export class DelegatedAsyncSequence extends AsyncSequenceMarker implem return this.#sequence.orderByDescending(selector, comparer); } - partition(equater?: MaybeAsyncEqualityComparison | undefined): AsyncSequence> { + partition(equater?: MaybeAsyncEqualityComparisonOrComparer | undefined): AsyncSequence> { return this.#sequence.partition(equater); } - partitionBy(selector: MaybeAsyncConverter, equater?: MaybeAsyncEqualityComparison | undefined): AsyncSequence> { + partitionBy(selector: MaybeAsyncConverter, equater?: MaybeAsyncEqualityComparisonOrComparer | undefined): AsyncSequence> { return this.#sequence.partitionBy(selector, equater); } - distinct(equater?: MaybeAsyncEqualityComparison | undefined): AsyncSequence { + distinct(equater?: MaybeAsyncEqualityComparisonOrComparer | undefined): AsyncSequence { return this.#sequence.distinct(equater); } - distinctBy(selector: MaybeAsyncConverter, equater?: MaybeAsyncEqualityComparison | undefined): AsyncSequence { + distinctBy(selector: MaybeAsyncConverter, equater?: MaybeAsyncEqualityComparisonOrComparer | undefined): AsyncSequence { return this.#sequence.distinctBy(selector, equater); } - union(sequence: MaybeAsyncIterable, equater?: MaybeAsyncEqualityComparison | undefined): AsyncSequence { + union(sequence: MaybeAsyncIterable, equater?: MaybeAsyncEqualityComparisonOrComparer | undefined): AsyncSequence { return this.#sequence.union(wrap(sequence), equater); } - unionBy(sequence: MaybeAsyncIterable, selector: MaybeAsyncConverter, equater?: MaybeAsyncEqualityComparison | undefined): AsyncSequence { + unionBy(sequence: MaybeAsyncIterable, selector: MaybeAsyncConverter, equater?: MaybeAsyncEqualityComparisonOrComparer | undefined): AsyncSequence { return this.#sequence.unionBy(wrap(sequence), selector, equater); } - except(sequence: MaybeAsyncIterable, equater?: MaybeAsyncEqualityComparison | undefined): AsyncSequence { + except(sequence: MaybeAsyncIterable, equater?: MaybeAsyncEqualityComparisonOrComparer | undefined): AsyncSequence { return this.#sequence.except(wrap(sequence), equater); } - exceptBy(sequence: MaybeAsyncIterable, selector: MaybeAsyncConverter, equater?: MaybeAsyncEqualityComparison | undefined): AsyncSequence { + exceptBy(sequence: MaybeAsyncIterable, selector: MaybeAsyncConverter, equater?: MaybeAsyncEqualityComparisonOrComparer | undefined): AsyncSequence { return this.#sequence.exceptBy(wrap(sequence), selector, equater); } - intersect(sequence: MaybeAsyncIterable, equater?: MaybeAsyncEqualityComparison | undefined): AsyncSequence { + intersect(sequence: MaybeAsyncIterable, equater?: MaybeAsyncEqualityComparisonOrComparer | undefined): AsyncSequence { return this.#sequence.intersect(wrap(sequence), equater); } - intersectBy(sequence: MaybeAsyncIterable, selector: MaybeAsyncConverter, equater?: MaybeAsyncEqualityComparison | undefined): AsyncSequence { + intersectBy(sequence: MaybeAsyncIterable, selector: MaybeAsyncConverter, equater?: MaybeAsyncEqualityComparisonOrComparer | undefined): AsyncSequence { return this.#sequence.intersectBy(wrap(sequence), selector, equater); } @@ -1383,9 +1379,9 @@ export class ConcatAsyncSequence extends BaseAsyncSequence { class DistinctAsyncSequence extends BaseAsyncSequence { readonly #sequence: AsyncSequence; - readonly #equater: MaybeAsyncEqualityComparison | undefined; + readonly #equater: MaybeAsyncEqualityComparisonOrComparer | undefined; - constructor(sequence: AsyncSequence, equater?: MaybeAsyncEqualityComparison) { + constructor(sequence: AsyncSequence, equater?: MaybeAsyncEqualityComparisonOrComparer) { super(); this.#sequence = sequence; @@ -1406,9 +1402,9 @@ class DistinctAsyncSequence extends BaseAsyncSequence { class DistinctByAsyncSequence extends BaseAsyncSequence { readonly #sequence: AsyncSequence; readonly #selector: MaybeAsyncConverter; - readonly #equater: MaybeAsyncEqualityComparison | undefined; + readonly #equater: MaybeAsyncEqualityComparisonOrComparer | undefined; - constructor(sequence: AsyncSequence, selector: MaybeAsyncConverter, equater?: MaybeAsyncEqualityComparison) { + constructor(sequence: AsyncSequence, selector: MaybeAsyncConverter, equater?: MaybeAsyncEqualityComparisonOrComparer) { super(); this.#sequence = sequence; @@ -1828,9 +1824,9 @@ class ZippedAsyncSequence extends BaseAsyncSequence<[T, U]> { class UnionAsyncSequence extends BaseAsyncSequence { readonly #first: AsyncSequence; readonly #second: AsyncSequence; - readonly #equater: MaybeAsyncEqualityComparison | undefined; + readonly #equater: MaybeAsyncEqualityComparisonOrComparer | undefined; - constructor(first: AsyncSequence, second: AsyncSequence, equater?: MaybeAsyncEqualityComparison) { + constructor(first: AsyncSequence, second: AsyncSequence, equater?: MaybeAsyncEqualityComparisonOrComparer) { super(); this.#first = first; @@ -1861,9 +1857,9 @@ class UnionByAsyncSequence extends BaseAsyncSequence { readonly #first: AsyncSequence; readonly #second: AsyncSequence; readonly #selector: MaybeAsyncConverter; - readonly #equater: MaybeAsyncEqualityComparison | undefined; + readonly #equater: MaybeAsyncEqualityComparisonOrComparer | undefined; - constructor(first: AsyncSequence, second: AsyncSequence, selector: MaybeAsyncConverter, equater?: MaybeAsyncEqualityComparison) { + constructor(first: AsyncSequence, second: AsyncSequence, selector: MaybeAsyncConverter, equater?: MaybeAsyncEqualityComparisonOrComparer) { super(); this.#first = first; @@ -1894,9 +1890,9 @@ class UnionByAsyncSequence extends BaseAsyncSequence { class ExceptAsyncSequence extends BaseAsyncSequence { readonly #first: AsyncSequence; readonly #second: AsyncSequence; - readonly #equater: MaybeAsyncEqualityComparison | undefined; + readonly #equater: MaybeAsyncEqualityComparisonOrComparer | undefined; - constructor(first: AsyncSequence, second: AsyncSequence, equater?: MaybeAsyncEqualityComparison) { + constructor(first: AsyncSequence, second: AsyncSequence, equater?: MaybeAsyncEqualityComparisonOrComparer) { super(); this.#first = first; @@ -1925,9 +1921,9 @@ class ExceptByAsyncSequence extends BaseAsyncSequence { readonly #first: AsyncSequence; readonly #second: AsyncSequence; readonly #selector: MaybeAsyncConverter; - readonly #equater: MaybeAsyncEqualityComparison | undefined; + readonly #equater: MaybeAsyncEqualityComparisonOrComparer | undefined; - constructor(first: AsyncSequence, second: AsyncSequence, selector: MaybeAsyncConverter, equater?: MaybeAsyncEqualityComparison) { + constructor(first: AsyncSequence, second: AsyncSequence, selector: MaybeAsyncConverter, equater?: MaybeAsyncEqualityComparisonOrComparer) { super(); this.#first = first; @@ -1956,9 +1952,9 @@ class ExceptByAsyncSequence extends BaseAsyncSequence { class IntersectAsyncSequence extends BaseAsyncSequence { readonly #first: AsyncSequence; readonly #second: AsyncSequence; - readonly #equater: MaybeAsyncEqualityComparison | undefined; + readonly #equater: MaybeAsyncEqualityComparisonOrComparer | undefined; - constructor(first: AsyncSequence, second: AsyncSequence, equater?: MaybeAsyncEqualityComparison) { + constructor(first: AsyncSequence, second: AsyncSequence, equater?: MaybeAsyncEqualityComparisonOrComparer) { super(); this.#first = first; @@ -1987,9 +1983,9 @@ class IntersectByAsyncSequence extends BaseAsyncSequence { readonly #first: AsyncSequence; readonly #second: AsyncSequence; readonly #selector: MaybeAsyncConverter; - readonly #equater: MaybeAsyncEqualityComparison | undefined; + readonly #equater: MaybeAsyncEqualityComparisonOrComparer | undefined; - constructor(first: AsyncSequence, second: AsyncSequence, selector: MaybeAsyncConverter, equater?: MaybeAsyncEqualityComparison) { + constructor(first: AsyncSequence, second: AsyncSequence, selector: MaybeAsyncConverter, equater?: MaybeAsyncEqualityComparisonOrComparer) { super(); this.#first = first; @@ -2041,9 +2037,9 @@ class GroupByAsyncSequence extends BaseAsyncSequence; readonly #keySelector: MaybeAsyncConverter; readonly #elementSelector: MaybeAsyncConverter; - readonly #keyComparer: MaybeAsyncEqualityComparison | undefined; + readonly #keyComparer: MaybeAsyncEqualityComparisonOrComparer | undefined; - constructor(sequence: AsyncSequence, keySelector: MaybeAsyncConverter, elementSelector?: MaybeAsyncConverter, keyComparer?: MaybeAsyncEqualityComparison) { + constructor(sequence: AsyncSequence, keySelector: MaybeAsyncConverter, elementSelector?: MaybeAsyncConverter, keyComparer?: MaybeAsyncEqualityComparisonOrComparer) { super(); this.#sequence = sequence; @@ -2114,9 +2110,9 @@ class JoinAsyncSequence extends BaseAsyncSequence readonly #firstKeySelector: MaybeAsyncConverter; readonly #secondKeySelector: MaybeAsyncConverter; readonly #resultSelector: MaybeAsyncBiConverter; - readonly #keyComparer: MaybeAsyncEqualityComparison; + readonly #keyComparer: AsyncEqualityComparer; - constructor(first: AsyncSequence, second: AsyncSequence, firstKeySelector: MaybeAsyncConverter, secondKeySelector: MaybeAsyncConverter, resultSelector?: MaybeAsyncBiConverter, keyComparer?: MaybeAsyncEqualityComparison) { + constructor(first: AsyncSequence, second: AsyncSequence, firstKeySelector: MaybeAsyncConverter, secondKeySelector: MaybeAsyncConverter, resultSelector?: MaybeAsyncBiConverter, keyComparer?: MaybeAsyncEqualityComparisonOrComparer) { super(); this.#first = first; @@ -2124,7 +2120,7 @@ class JoinAsyncSequence extends BaseAsyncSequence this.#firstKeySelector = firstKeySelector; this.#secondKeySelector = secondKeySelector; this.#resultSelector = resultSelector ?? identity as MaybeAsyncBiConverter; - this.#keyComparer = keyComparer ?? strictEquals; + this.#keyComparer = keyComparer ? asAsyncEqualityComparer(keyComparer) : defaultAsyncEqualityComparer; } override async *iterator() { @@ -2134,7 +2130,7 @@ class JoinAsyncSequence extends BaseAsyncSequence for await (const secondObj of this.#second) { const secondKey = await this.#secondKeySelector(secondObj); - if (await this.#keyComparer(firstKey, secondKey)) { + if (await this.#keyComparer.equals(firstKey, secondKey)) { yield await this.#resultSelector(firstObj, secondObj); } } @@ -2148,9 +2144,9 @@ class GroupJoinAsyncSequence extends BaseAsyncSeq readonly #firstKeySelector: MaybeAsyncConverter; readonly #secondKeySelector: MaybeAsyncConverter; readonly #resultSelector: MaybeAsyncBiConverter, TResult>; - readonly #keyComparer: MaybeAsyncEqualityComparison; + readonly #keyComparer: AsyncEqualityComparer; - constructor(first: AsyncSequence, second: AsyncSequence, firstKeySelector: MaybeAsyncConverter, secondKeySelector: MaybeAsyncConverter, resultSelector?: MaybeAsyncBiConverter, TResult>, keyComparer?: MaybeAsyncEqualityComparison) { + constructor(first: AsyncSequence, second: AsyncSequence, firstKeySelector: MaybeAsyncConverter, secondKeySelector: MaybeAsyncConverter, resultSelector?: MaybeAsyncBiConverter, TResult>, keyComparer?: MaybeAsyncEqualityComparisonOrComparer) { super(); this.#first = first; @@ -2158,7 +2154,7 @@ class GroupJoinAsyncSequence extends BaseAsyncSeq this.#firstKeySelector = firstKeySelector; this.#secondKeySelector = secondKeySelector; this.#resultSelector = resultSelector ?? GroupJoinAsyncSequence.#defaultResultSelector as MaybeAsyncBiConverter, TResult>; - this.#keyComparer = keyComparer ?? strictEquals; + this.#keyComparer = keyComparer ? asAsyncEqualityComparer(keyComparer) : defaultAsyncEqualityComparer; } static #defaultResultSelector(first: TOuter, second: AsyncSequence) { @@ -2173,7 +2169,7 @@ class GroupJoinAsyncSequence extends BaseAsyncSeq for await (const secondObj of this.#second) { const secondKey = await this.#secondKeySelector(secondObj); - if (await this.#keyComparer(firstKey, secondKey)) { + if (await this.#keyComparer.equals(firstKey, secondKey)) { secondObjs.push(secondObj); } } @@ -2187,22 +2183,22 @@ class RemoveAsyncSequence extends BaseAsyncSequence { readonly #sequence: AsyncSequence; readonly #obj: T; readonly #all: boolean; - readonly #equater: MaybeAsyncEqualityComparison; + readonly #equater: AsyncEqualityComparer; - constructor(sequence: AsyncSequence, obj: T, all?: boolean, equater?: MaybeAsyncEqualityComparison) { + constructor(sequence: AsyncSequence, obj: T, all?: boolean, equater?: MaybeAsyncEqualityComparisonOrComparer) { super(); this.#sequence = sequence; this.#obj = obj; this.#all = all ?? false; - this.#equater = equater ?? strictEquals; + this.#equater = equater ? asAsyncEqualityComparer(equater) : defaultAsyncEqualityComparer; } override async *iterator() { let gotOne = false; for await (const obj of this.#sequence) { - if (await this.#equater(this.#obj, obj)) { + if (await this.#equater.equals(this.#obj, obj)) { if (this.#all) { continue; } @@ -2246,13 +2242,13 @@ class CacheAsyncSequence extends BaseAsyncSequence { class PartitionAsyncSequence extends BaseAsyncSequence> { readonly #sequence: AsyncSequence; - readonly #equater: MaybeAsyncEqualityComparison; + readonly #equater: MaybeAsyncEqualityComparisonOrComparer | undefined; - constructor(sequence: AsyncSequence, equater: MaybeAsyncEqualityComparison | undefined) { + constructor(sequence: AsyncSequence, equater: MaybeAsyncEqualityComparisonOrComparer | undefined) { super(); this.#sequence = sequence; - this.#equater = equater ?? strictEquals; + this.#equater = equater; } override async *iterator() { @@ -2277,14 +2273,14 @@ class PartitionAsyncSequence extends BaseAsyncSequence> { class PartitionByAsyncSequence extends BaseAsyncSequence> { readonly #sequence: AsyncSequence; readonly #selector: MaybeAsyncConverter; - readonly #equater: MaybeAsyncEqualityComparison; + readonly #equater: MaybeAsyncEqualityComparisonOrComparer | undefined; - constructor(sequence: AsyncSequence, selector: MaybeAsyncConverter, equater: MaybeAsyncEqualityComparison | undefined) { + constructor(sequence: AsyncSequence, selector: MaybeAsyncConverter, equater: MaybeAsyncEqualityComparisonOrComparer | undefined) { super(); this.#sequence = sequence; this.#selector = selector; - this.#equater = equater ?? strictEquals; + this.#equater = equater; } override async *iterator() { diff --git a/src/async/types.ts b/src/async/types.ts index 71e841c..767ffd9 100644 --- a/src/async/types.ts +++ b/src/async/types.ts @@ -1,6 +1,6 @@ import { Collector } from "../collector/types.js"; import { MaybeAsyncComparisonOrComparer, AsyncComparer } from "../comparer/types.js"; -import { MaybeAsyncEqualityComparison } from "../equality-comparer/types.js"; +import { MaybeAsyncEqualityComparisonOrComparer } from "../equality-comparer/types.js"; import { AsyncRandomOptions } from "../random/types.js"; import { MaybeAsyncAnyPredicate, MaybeAsyncConverter, MaybeAsyncBiConverter, MaybeAsyncAccumulator, MaybeAsyncAction, MaybeAsyncFunction, MaybePromise, MaybeAsyncIterable } from "../types.js"; @@ -22,24 +22,24 @@ export interface AsyncSequence extends AsyncIterable { where(predicate: MaybeAsyncAnyPredicate): AsyncSequence; where(predicate: MaybeAsyncAnyPredicate): AsyncSequence; - groupBy(keySelector: MaybeAsyncConverter, elementSelector?: undefined, keyComparer?: MaybeAsyncEqualityComparison): AsyncSequence>; - groupBy(keySelector: MaybeAsyncConverter, elementSelector: MaybeAsyncConverter, keyComparer?: MaybeAsyncEqualityComparison): AsyncSequence>; + groupBy(keySelector: MaybeAsyncConverter, elementSelector?: undefined, keyComparer?: MaybeAsyncEqualityComparisonOrComparer): AsyncSequence>; + groupBy(keySelector: MaybeAsyncConverter, elementSelector: MaybeAsyncConverter, keyComparer?: MaybeAsyncEqualityComparisonOrComparer): AsyncSequence>; - join(sequence: MaybeAsyncIterable, firstKeySelector: MaybeAsyncConverter, secondKeySelector: MaybeAsyncConverter, resultSelector?: undefined, keyComparer?: MaybeAsyncEqualityComparison): AsyncSequence<[TElement, TOther]>; - join(sequence: MaybeAsyncIterable, firstKeySelector: MaybeAsyncConverter, secondKeySelector: MaybeAsyncConverter, resultSelector: MaybeAsyncBiConverter, keyComparer?: MaybeAsyncEqualityComparison): AsyncSequence; + join(sequence: MaybeAsyncIterable, firstKeySelector: MaybeAsyncConverter, secondKeySelector: MaybeAsyncConverter, resultSelector?: undefined, keyComparer?: MaybeAsyncEqualityComparisonOrComparer): AsyncSequence<[TElement, TOther]>; + join(sequence: MaybeAsyncIterable, firstKeySelector: MaybeAsyncConverter, secondKeySelector: MaybeAsyncConverter, resultSelector: MaybeAsyncBiConverter, keyComparer?: MaybeAsyncEqualityComparisonOrComparer): AsyncSequence; - groupJoin(sequence: MaybeAsyncIterable, firstKeySelector: MaybeAsyncConverter, secondKeySelector: MaybeAsyncConverter, resultSelector?: undefined, keyComparer?: MaybeAsyncEqualityComparison): AsyncSequence>; - groupJoin(sequence: MaybeAsyncIterable, firstKeySelector: MaybeAsyncConverter, secondKeySelector: MaybeAsyncConverter, resultSelector: MaybeAsyncBiConverter, TResult>, keyComparer?: MaybeAsyncEqualityComparison): AsyncSequence; + groupJoin(sequence: MaybeAsyncIterable, firstKeySelector: MaybeAsyncConverter, secondKeySelector: MaybeAsyncConverter, resultSelector?: undefined, keyComparer?: MaybeAsyncEqualityComparisonOrComparer): AsyncSequence>; + groupJoin(sequence: MaybeAsyncIterable, firstKeySelector: MaybeAsyncConverter, secondKeySelector: MaybeAsyncConverter, resultSelector: MaybeAsyncBiConverter, TResult>, keyComparer?: MaybeAsyncEqualityComparisonOrComparer): AsyncSequence; - contains(obj: TElement, equater?: MaybeAsyncEqualityComparison): Promise; + contains(obj: TElement, equater?: MaybeAsyncEqualityComparisonOrComparer): Promise; - sequenceEquals(sequence: MaybeAsyncIterable, equater?: MaybeAsyncEqualityComparison): Promise; + sequenceEquals(sequence: MaybeAsyncIterable, equater?: MaybeAsyncEqualityComparisonOrComparer): Promise; append(obj: TElement): AsyncSequence; prepend(obj: TElement): AsyncSequence; - remove(obj: TElement, all?: boolean, equater?: MaybeAsyncEqualityComparison): AsyncSequence; + remove(obj: TElement, all?: boolean, equater?: MaybeAsyncEqualityComparisonOrComparer): AsyncSequence; concat(...sequences: MaybeAsyncIterable[]): AsyncSequence; @@ -74,20 +74,20 @@ export interface AsyncSequence extends AsyncIterable { orderDescending(comparer?: MaybeAsyncComparisonOrComparer): AsyncSequence; orderByDescending(selector: MaybeAsyncConverter, comparer?: MaybeAsyncComparisonOrComparer): AsyncSequence; - partition(equater?: MaybeAsyncEqualityComparison): AsyncSequence>; - partitionBy(selector: MaybeAsyncConverter, equater?: MaybeAsyncEqualityComparison): AsyncSequence>; + partition(equater?: MaybeAsyncEqualityComparisonOrComparer): AsyncSequence>; + partitionBy(selector: MaybeAsyncConverter, equater?: MaybeAsyncEqualityComparisonOrComparer): AsyncSequence>; - distinct(equater?: MaybeAsyncEqualityComparison): AsyncSequence; - distinctBy(selector: MaybeAsyncConverter, equater?: MaybeAsyncEqualityComparison): AsyncSequence; + distinct(equater?: MaybeAsyncEqualityComparisonOrComparer): AsyncSequence; + distinctBy(selector: MaybeAsyncConverter, equater?: MaybeAsyncEqualityComparisonOrComparer): AsyncSequence; - union(sequence: MaybeAsyncIterable, equater?: MaybeAsyncEqualityComparison): AsyncSequence; - unionBy(sequence: MaybeAsyncIterable, selector: MaybeAsyncConverter, equater?: MaybeAsyncEqualityComparison): AsyncSequence; + union(sequence: MaybeAsyncIterable, equater?: MaybeAsyncEqualityComparisonOrComparer): AsyncSequence; + unionBy(sequence: MaybeAsyncIterable, selector: MaybeAsyncConverter, equater?: MaybeAsyncEqualityComparisonOrComparer): AsyncSequence; - except(sequence: MaybeAsyncIterable, equater?: MaybeAsyncEqualityComparison): AsyncSequence; - exceptBy(sequence: MaybeAsyncIterable, selector: MaybeAsyncConverter, equater?: MaybeAsyncEqualityComparison): AsyncSequence; + except(sequence: MaybeAsyncIterable, equater?: MaybeAsyncEqualityComparisonOrComparer): AsyncSequence; + exceptBy(sequence: MaybeAsyncIterable, selector: MaybeAsyncConverter, equater?: MaybeAsyncEqualityComparisonOrComparer): AsyncSequence; - intersect(sequence: MaybeAsyncIterable, equater?: MaybeAsyncEqualityComparison): AsyncSequence; - intersectBy(sequence: MaybeAsyncIterable, selector: MaybeAsyncConverter, equater?: MaybeAsyncEqualityComparison): AsyncSequence; + intersect(sequence: MaybeAsyncIterable, equater?: MaybeAsyncEqualityComparisonOrComparer): AsyncSequence; + intersectBy(sequence: MaybeAsyncIterable, selector: MaybeAsyncConverter, equater?: MaybeAsyncEqualityComparisonOrComparer): AsyncSequence; all(predicate: MaybeAsyncAnyPredicate): Promise; any(predicate: MaybeAsyncAnyPredicate): Promise; diff --git a/src/comparer/async.ts b/src/comparer/async.ts index ca9edfb..23c5408 100644 --- a/src/comparer/async.ts +++ b/src/comparer/async.ts @@ -1,16 +1,16 @@ import { MaybeAsyncConverter } from "../types.js"; import { Nullable } from "../utils.js"; -import { AsyncComparer, MaybeAsyncComparisonOrComparer, Comparer, MaybeAsyncComparison, AsyncComparison } from "./types.js"; +import { AsyncComparer, AsyncComparison, Comparer, MaybeAsyncComparison, MaybeAsyncComparisonOrComparer } from "./types.js"; export function isAsyncComparer(obj: any): obj is AsyncComparer { return obj instanceof BaseAsyncComparer; } export function asAsyncComparer(comparer: MaybeAsyncComparisonOrComparer): AsyncComparer { - return typeof comparer === "function" ? createAsyncComparer(comparer) : isAsyncComparer(comparer) ? comparer : new WrappedAsyncComparer(comparer); + return typeof comparer === "function" ? createAsyncComparer(comparer) : isAsyncComparer(comparer) ? comparer : fromSyncComparer(comparer); } -export function fromSync(comparer: Comparer): AsyncComparer { +export function fromSyncComparer(comparer: Comparer): AsyncComparer { return new WrappedAsyncComparer(comparer); } diff --git a/src/comparer/sync.ts b/src/comparer/sync.ts index f8227e4..f5cb18e 100644 --- a/src/comparer/sync.ts +++ b/src/comparer/sync.ts @@ -1,6 +1,6 @@ import { Converter } from "../types.js"; import { Nullable } from "../utils.js"; -import { fromSync } from "./async.js"; +import { fromSyncComparer } from "./async.js"; import { Comparer, ComparisonOrComparer, Comparison, AsyncComparer } from "./types.js"; export function isComparer(obj: any): obj is Comparer { @@ -67,7 +67,7 @@ export abstract class BaseComparer implements Comparer { } public toAsync(): AsyncComparer { - return fromSync(this); + return fromSyncComparer(this); } public nullAwareComparer(): Comparer> { diff --git a/src/equality-comparer/async.ts b/src/equality-comparer/async.ts new file mode 100644 index 0000000..02fc651 --- /dev/null +++ b/src/equality-comparer/async.ts @@ -0,0 +1,173 @@ +import { MaybeAsyncConverter } from "../types.js"; +import { Nullable } from "../utils.js"; +import { AsyncEqualityComparer, AsyncEqualityComparison, EqualityComparer, MaybeAsyncEqualityComparison, MaybeAsyncEqualityComparisonOrComparer } from "./types.js"; + +export function isAsyncEqualityComparer(obj: any): obj is AsyncEqualityComparer { + return obj instanceof BaseAsyncEqualityComparer; +} + +export function asAsyncEqualityComparer(equalityComparer: MaybeAsyncEqualityComparisonOrComparer): AsyncEqualityComparer { + return typeof equalityComparer === "function" ? createAsyncEqualityComparer(equalityComparer) : isAsyncEqualityComparer(equalityComparer) ? equalityComparer : fromSyncEqualityComparer(equalityComparer); +} + +export function fromSyncEqualityComparer(equalityComparer: EqualityComparer): AsyncEqualityComparer { + return new WrappedAsyncEqualityComparer(equalityComparer); +} + +export function createAsyncEqualityComparer(equalityComparison: MaybeAsyncEqualityComparison): AsyncEqualityComparer { + return new SimpleAsyncEqualityComparer(equalityComparison); +} + +export function createAsyncEqualityComparerUsing(projection: MaybeAsyncConverter, equalityComparison?: MaybeAsyncEqualityComparisonOrComparer): AsyncEqualityComparer { + return new MappedAsyncEqualityComparer(projection, equalityComparison); +} + +export function combineNullableAsyncEqualityComparers(equalityComparers: Nullable>[]) { + let result = defaultAsyncEqualityComparer; + + for (const equalityComparer of equalityComparers) { + if (!equalityComparer) { + continue; + } + + result = result.then(asAsyncEqualityComparer(equalityComparer)); + } + + return result === defaultAsyncEqualityComparer ? undefined : result; +} + +export abstract class BaseAsyncEqualityComparer implements AsyncEqualityComparer { + #cachedBoundEqualityComparison: AsyncEqualityComparison | undefined; + + public abstract equals(a: T, b: T): Promise; + + public equalityComparison(): AsyncEqualityComparison { + return this.#cachedBoundEqualityComparison ??= this.equals.bind(this); + } + + public opposite(): AsyncEqualityComparer { + return new OppositeAsyncEqualityComparer(this); + } + + public then(equalityComparer: AsyncEqualityComparer): AsyncEqualityComparer { + return new ThenAsyncEqualityComparer(this, equalityComparer); + } + + public thenEquals(equalityComparison: MaybeAsyncEqualityComparison): AsyncEqualityComparer { + return this.then(createAsyncEqualityComparer(equalityComparison)); + } + + public thenEqualsUsing(projection: MaybeAsyncConverter, equalityComparison?: MaybeAsyncEqualityComparisonOrComparer): AsyncEqualityComparer { + return this.then(createAsyncEqualityComparerUsing(projection, equalityComparison)); + } +} + +class WrappedAsyncEqualityComparer extends BaseAsyncEqualityComparer { + readonly #base: EqualityComparer; + + constructor(base: EqualityComparer) { + super(); + + this.#base = base; + } + + public override async equals(a: T, b: T) { + return this.#base.equals(a, b); + } +} + +class SimpleAsyncEqualityComparer extends BaseAsyncEqualityComparer { + readonly #equalityComparison: MaybeAsyncEqualityComparison; + + public constructor(equalityComparison: MaybeAsyncEqualityComparison) { + super(); + + this.#equalityComparison = equalityComparison; + } + + public override async equals(a: T, b: T): Promise { + return await this.#equalityComparison(a, b); + } +} + +class MappedAsyncEqualityComparer extends BaseAsyncEqualityComparer { + readonly #projection: MaybeAsyncConverter; + readonly #equalityComparison: AsyncEqualityComparer; + + public constructor(projection: MaybeAsyncConverter, equalityComparison?: MaybeAsyncEqualityComparisonOrComparer) { + super(); + + this.#projection = projection; + this.#equalityComparison = equalityComparison ? asAsyncEqualityComparer(equalityComparison) : defaultAsyncEqualityComparer; + } + + public override async equals(a: T, b: T): Promise { + return await this.#equalityComparison.equals(await this.#projection(a), await this.#projection(b)); + } +} + +class OppositeAsyncEqualityComparer extends BaseAsyncEqualityComparer { + readonly #base: AsyncEqualityComparer; + + public constructor(base: AsyncEqualityComparer) { + super(); + + this.#base = base; + } + + public override async equals(a: T, b: T): Promise { + return !(await this.#base.equals(a, b)); + } + + public override opposite(): AsyncEqualityComparer { + return this.#base; + } +} + +class ThenAsyncEqualityComparer extends BaseAsyncEqualityComparer { + readonly #base: AsyncEqualityComparer; + readonly #equalityComparer: AsyncEqualityComparer; + + public constructor(base: AsyncEqualityComparer, equalityComparer: AsyncEqualityComparer) { + super(); + + this.#base = base; + this.#equalityComparer = equalityComparer; + } + + public override async equals(a: T, b: T) { + return await this.#base.equals(a, b) && await this.#equalityComparer.equals(a, b); + } +} + +export const looseAsyncEqualityComparer: AsyncEqualityComparer = new class LooseAsyncEqualityComparer extends BaseAsyncEqualityComparer { + public override async equals(a: any, b: any): Promise { + return a == b; + } +}; +export const strictAsyncEqualityComparer: AsyncEqualityComparer = new class StrictAsyncEqualityComparer extends BaseAsyncEqualityComparer { + public override async equals(a: any, b: any): Promise { + return a === b; + } +}; +export const sameValueAsyncEqualityComparer: AsyncEqualityComparer = new class SameValueAsyncEqualityComparer extends BaseAsyncEqualityComparer { + public override async equals(a: any, b: any): Promise { + return Object.is(a, b); + } +}; + +export const defaultAsyncEqualityComparer: AsyncEqualityComparer = new class DefaultAsyncEqualityComparer extends BaseAsyncEqualityComparer { + public override async equals(a: any, b: any): Promise { + return a === b; + } +}; + +export function getDefaultAsyncEqualityComparer(): AsyncEqualityComparer { + return defaultAsyncEqualityComparer; +} + +export const dateAsyncEqualityComparer: AsyncEqualityComparer = new class DateAsyncEqualityComparer extends BaseAsyncEqualityComparer { + public override async equals(a: Date, b: Date): Promise { + return a.getTime() === b.getTime(); + } +}; diff --git a/src/equality-comparer/sync.ts b/src/equality-comparer/sync.ts index c2670f5..d1cf0f1 100644 --- a/src/equality-comparer/sync.ts +++ b/src/equality-comparer/sync.ts @@ -2,30 +2,14 @@ import { Converter } from "../types.js"; import { Nullable } from "../utils.js"; import { EqualityComparer, EqualityComparison, EqualityComparisonOrComparer } from "./types.js"; -export function looseEquals(a: any, b: any) { - return a == b; -} - -export function strictEquals(a: any, b: any) { - return a === b; -} - -export function sameValue(a: any, b: any) { - return Object.is(a, b); -} - export function isEqualityComparer(obj: any): obj is EqualityComparer { return obj instanceof BaseEqualityComparer; } -export function asEqualityComparer(equalityComparer: EqualityComparisonOrComparer) { +export function asEqualityComparer(equalityComparer: EqualityComparisonOrComparer): EqualityComparer { return typeof equalityComparer === "function" ? createEqualityComparer(equalityComparer) : equalityComparer; } -export function asEqualityComparison(equalityComparer: EqualityComparisonOrComparer) { - return typeof equalityComparer === "function" ? equalityComparer : equalityComparer.equalityComparison(); -} - export function createEqualityComparer(equalityComparison: EqualityComparison): EqualityComparer { return new SimpleEqualityComparer(equalityComparison); } @@ -34,10 +18,6 @@ export function createEqualityComparerUsing(projection: Conver return new MappedEqualityComparer(projection, equalityComparison); } -export function oppositeEqualityComparison(equalityComparison: EqualityComparison): EqualityComparison { - return (a, b) => !equalityComparison(a, b); -} - export function combineNullableEqualityComparers(equalityComparers: Nullable>[]) { let result = defaultEqualityComparer; @@ -146,6 +126,22 @@ class ThenEqualityComparer extends BaseEqualityComparer { } } +export const looseEqualityComparer: EqualityComparer = new class LooseEqualityComparer extends BaseEqualityComparer { + public override equals(a: any, b: any): boolean { + return a == b; + } +}; +export const strictEqualityComparer: EqualityComparer = new class StrictEqualityComparer extends BaseEqualityComparer { + public override equals(a: any, b: any): boolean { + return a === b; + } +}; +export const sameValueEqualityComparer: EqualityComparer = new class SameValueEqualityComparer extends BaseEqualityComparer { + public override equals(a: any, b: any): boolean { + return Object.is(a, b); + } +}; + export const defaultEqualityComparer: EqualityComparer = new class DefaultEqualityComparer extends BaseEqualityComparer { public override equals(a: any, b: any): boolean { return a === b; @@ -161,7 +157,3 @@ export const dateEqualityComparer: EqualityComparer = new class DateEquali return a.getTime() === b.getTime(); } }; - -export const looseEqualityComparer: EqualityComparer = new SimpleEqualityComparer(looseEquals); -export const strictEqualityComparer: EqualityComparer = new SimpleEqualityComparer(strictEquals); -export const sameValueEqualityComparer: EqualityComparer = new SimpleEqualityComparer(sameValue); diff --git a/src/equality-comparer/types.ts b/src/equality-comparer/types.ts index 3c63b70..1fea91c 100644 --- a/src/equality-comparer/types.ts +++ b/src/equality-comparer/types.ts @@ -1,4 +1,4 @@ -import { Converter, MaybeAsyncFunction } from "../types.js"; +import { AsyncFunction, Converter, MaybeAsyncConverter, MaybeAsyncFunction } from "../types.js"; export interface EqualityComparer { equals(a: T, b: T): boolean; @@ -9,7 +9,20 @@ export interface EqualityComparer { thenEqualsUsing(projection: Converter, equalityComparison?: EqualityComparisonOrComparer): EqualityComparer; } +export interface AsyncEqualityComparer { + equals(a: T, b: T): Promise; + equalityComparison(): AsyncEqualityComparison; + opposite(): AsyncEqualityComparer; + then(equalityComparer: AsyncEqualityComparer): AsyncEqualityComparer; + thenEquals(equalityComparison: AsyncEqualityComparison): AsyncEqualityComparer; + thenEqualsUsing(projection: MaybeAsyncConverter, equalityComparison?: AsyncEqualityComparisonOrComparer): AsyncEqualityComparer; +} + export type EqualityComparison = (first: T, second: T) => boolean; export type EqualityComparisonOrComparer = EqualityComparison | EqualityComparer; +export type AsyncEqualityComparison = AsyncFunction>; export type MaybeAsyncEqualityComparison = MaybeAsyncFunction>; +export type AsyncEqualityComparisonOrComparer = AsyncEqualityComparison | AsyncEqualityComparer; +export type MaybeAsyncEqualityComparisonOrComparer = MaybeAsyncEqualityComparison | EqualityComparer | AsyncEqualityComparer; + diff --git a/src/equality-map/impl.ts b/src/equality-map/impl.ts index 5dacf8d..b2f6e8f 100644 --- a/src/equality-map/impl.ts +++ b/src/equality-map/impl.ts @@ -1,5 +1,6 @@ +import { asAsyncEqualityComparer } from "../equality-comparer/async.js"; import { asEqualityComparer } from "../equality-comparer/sync.js"; -import { EqualityComparer, EqualityComparisonOrComparer, MaybeAsyncEqualityComparison } from "../equality-comparer/types.js"; +import { AsyncEqualityComparer, EqualityComparer, EqualityComparisonOrComparer, MaybeAsyncEqualityComparisonOrComparer } from "../equality-comparer/types.js"; import { MaybeAsyncIterable } from "../types.js"; import { AsyncEqualityMap, EqualityMap, EqualityMapEntry } from "./types.js"; @@ -203,10 +204,10 @@ export class NativeAsyncEqualityMap implements AsyncEqualityMap { export class CustomAsyncEqualityMap implements AsyncEqualityMap { readonly #list: EqualityMapEntry[] = []; - readonly #keyComparer: MaybeAsyncEqualityComparison; + readonly #keyComparer: AsyncEqualityComparer; - constructor(keyComparer: MaybeAsyncEqualityComparison) { - this.#keyComparer = keyComparer; + constructor(keyComparer: MaybeAsyncEqualityComparisonOrComparer) { + this.#keyComparer = asAsyncEqualityComparer(keyComparer); } get size() { @@ -215,7 +216,7 @@ export class CustomAsyncEqualityMap implements AsyncEqualityMap { async get(key: K) { for (const entry of this.#list) { - if (await this.#keyComparer(key, entry[0])) { + if (await this.#keyComparer.equals(key, entry[0])) { return entry[1]; } } @@ -225,7 +226,7 @@ export class CustomAsyncEqualityMap implements AsyncEqualityMap { async set(key: K, value: V) { for (const entry of this.#list) { - if (await this.#keyComparer(key, entry[0])) { + if (await this.#keyComparer.equals(key, entry[0])) { const previous = entry[1]; entry[1] = value; return previous; @@ -245,7 +246,7 @@ export class CustomAsyncEqualityMap implements AsyncEqualityMap { async contains(key: K) { for (const entry of this.#list) { - if (await this.#keyComparer(key, entry[0])) { + if (await this.#keyComparer.equals(key, entry[0])) { return true; } } @@ -255,7 +256,7 @@ export class CustomAsyncEqualityMap implements AsyncEqualityMap { async remove(key: K) { for (let i = 0; i < this.#list.length; i++) { - if (await this.#keyComparer(key, this.#list[i][0])) { + if (await this.#keyComparer.equals(key, this.#list[i][0])) { const removed = this.#list.splice(i, 1); return removed[0][1]; } diff --git a/src/equality-map/index.ts b/src/equality-map/index.ts index 1ef22f3..f7adea4 100644 --- a/src/equality-map/index.ts +++ b/src/equality-map/index.ts @@ -1,4 +1,4 @@ -import { EqualityComparisonOrComparer, MaybeAsyncEqualityComparison } from "../equality-comparer/types.js"; +import { EqualityComparisonOrComparer, MaybeAsyncEqualityComparisonOrComparer } from "../equality-comparer/types.js"; import { CustomAsyncEqualityMap, CustomEqualityMap, NativeAsyncEqualityMap, NativeEqualityMap } from "./impl.js"; import { AsyncEqualityMap, EqualityMap } from "./types.js"; @@ -6,6 +6,6 @@ export function createEqualityMap(keyComparer?: EqualityComparisonOrCompar return keyComparer ? new CustomEqualityMap(keyComparer) : new NativeEqualityMap(); } -export function createAsyncEqualityMap(keyComparer?: MaybeAsyncEqualityComparison): AsyncEqualityMap { +export function createAsyncEqualityMap(keyComparer?: MaybeAsyncEqualityComparisonOrComparer): AsyncEqualityMap { return keyComparer ? new CustomAsyncEqualityMap(keyComparer) : new NativeAsyncEqualityMap(); } diff --git a/src/equality-set/impl.ts b/src/equality-set/impl.ts index 8eeae30..a98b244 100644 --- a/src/equality-set/impl.ts +++ b/src/equality-set/impl.ts @@ -1,5 +1,6 @@ +import { asAsyncEqualityComparer } from "../equality-comparer/async.js"; import { asEqualityComparer } from "../equality-comparer/sync.js"; -import { EqualityComparer, EqualityComparisonOrComparer, MaybeAsyncEqualityComparison } from "../equality-comparer/types.js"; +import { AsyncEqualityComparer, EqualityComparer, EqualityComparisonOrComparer, MaybeAsyncEqualityComparisonOrComparer } from "../equality-comparer/types.js"; import { MaybeAsyncIterable } from "../types.js"; import { AsyncEqualitySet, EqualitySet } from "./types.js"; @@ -167,10 +168,10 @@ export class NativeAsyncEqualitySet implements AsyncEqualitySet { export class CustomAsyncEqualitySet implements AsyncEqualitySet { readonly #list: T[] = []; - readonly #equater: MaybeAsyncEqualityComparison; + readonly #equater: AsyncEqualityComparer; - constructor(equater: MaybeAsyncEqualityComparison) { - this.#equater = equater; + constructor(equater: MaybeAsyncEqualityComparisonOrComparer) { + this.#equater = asAsyncEqualityComparer(equater); } get size() { @@ -201,7 +202,7 @@ export class CustomAsyncEqualitySet implements AsyncEqualitySet { async contains(value: T) { for (const val of this.#list) { - if (await this.#equater(value, val)) { + if (await this.#equater.equals(value, val)) { return true; } } @@ -213,7 +214,7 @@ export class CustomAsyncEqualitySet implements AsyncEqualitySet { const length = this.#list.length; for (let i = 0; i < length; i++) { - if (await this.#equater(value, this.#list[i])) { + if (await this.#equater.equals(value, this.#list[i])) { this.#list.splice(i, 1); return true; } diff --git a/src/equality-set/index.ts b/src/equality-set/index.ts index f814368..43fd96a 100644 --- a/src/equality-set/index.ts +++ b/src/equality-set/index.ts @@ -1,4 +1,4 @@ -import { EqualityComparisonOrComparer, MaybeAsyncEqualityComparison } from "../equality-comparer/types.js"; +import { EqualityComparisonOrComparer, MaybeAsyncEqualityComparisonOrComparer } from "../equality-comparer/types.js"; import { CustomAsyncEqualitySet, CustomEqualitySet, NativeAsyncEqualitySet, NativeEqualitySet } from "./impl.js"; import { AsyncEqualitySet, EqualitySet } from "./types.js"; @@ -6,6 +6,6 @@ export function createEqualitySet(equater?: EqualityComparisonOrComparer): return equater ? new CustomEqualitySet(equater) : new NativeEqualitySet(); } -export function createAsyncEqualitySet(equater?: MaybeAsyncEqualityComparison): AsyncEqualitySet { +export function createAsyncEqualitySet(equater?: MaybeAsyncEqualityComparisonOrComparer): AsyncEqualitySet { return equater ? new CustomAsyncEqualitySet(equater) : new NativeAsyncEqualitySet(); } diff --git a/src/sync/impl.ts b/src/sync/impl.ts index 312f2a6..e706638 100644 --- a/src/sync/impl.ts +++ b/src/sync/impl.ts @@ -3,8 +3,8 @@ import { AsyncSequence } from "../async/types.js"; import { Collector } from "../collector/types.js"; import { asComparer, combineNullableComparers, createComparerUsing, defaultComparer } from "../comparer/sync.js"; import { ComparisonOrComparer, Comparer } from "../comparer/types.js"; -import { strictEquals } from "../equality-comparer/sync.js"; -import { EqualityComparison } from "../equality-comparer/types.js"; +import { asEqualityComparer, defaultEqualityComparer } from "../equality-comparer/sync.js"; +import { EqualityComparer, EqualityComparisonOrComparer } from "../equality-comparer/types.js"; import { createEqualityMap } from "../equality-map/index.js"; import { createEqualitySet } from "../equality-set/index.js"; import { createQueue } from "../queue.js"; @@ -50,25 +50,23 @@ export abstract class BaseSequence extends SequenceMarker implements S return new WhereSequence(this, predicate); } - groupBy(keySelector: Converter, elementSelector?: Converter, keyComparer?: EqualityComparison): Sequence> { + groupBy(keySelector: Converter, elementSelector?: Converter, keyComparer?: EqualityComparisonOrComparer): Sequence> { return new GroupBySequence(this, keySelector, elementSelector, keyComparer); } - join(sequence: Iterable, firstKeySelector: Converter, secondKeySelector: Converter, resultSelector?: BiConverter, keyComparer?: EqualityComparison): Sequence { + join(sequence: Iterable, firstKeySelector: Converter, secondKeySelector: Converter, resultSelector?: BiConverter, keyComparer?: EqualityComparisonOrComparer): Sequence { return new JoinSequence(this, wrap(sequence), firstKeySelector, secondKeySelector, resultSelector, keyComparer); } - groupJoin(sequence: Iterable, firstKeySelector: Converter, secondKeySelector: Converter, resultSelector?: BiConverter, TResult>, keyComparer?: EqualityComparison): Sequence { + groupJoin(sequence: Iterable, firstKeySelector: Converter, secondKeySelector: Converter, resultSelector?: BiConverter, TResult>, keyComparer?: EqualityComparisonOrComparer): Sequence { return new GroupJoinSequence(this, wrap(sequence), firstKeySelector, secondKeySelector, resultSelector, keyComparer); } - contains(obj: TElement, equater?: EqualityComparison) { - if (!equater) { - equater = strictEquals; - } + contains(obj: TElement, equater?: EqualityComparisonOrComparer) { + equater = equater ? asEqualityComparer(equater) : defaultEqualityComparer; for (const element of this) { - if (equater(element, obj)) { + if (equater.equals(element, obj)) { return true; } } @@ -76,7 +74,7 @@ export abstract class BaseSequence extends SequenceMarker implements S return false; } - sequenceEquals(sequence: Iterable, equater?: EqualityComparison) { + sequenceEquals(sequence: Iterable, equater?: EqualityComparisonOrComparer) { if (this === sequence) { return true; } @@ -90,9 +88,7 @@ export abstract class BaseSequence extends SequenceMarker implements S return false; } - if (!equater) { - equater = strictEquals; - } + equater = equater ? asEqualityComparer(equater) : defaultEqualityComparer; const thisIterator = this.iterator(); const thatIterator = other.iterator(); @@ -109,7 +105,7 @@ export abstract class BaseSequence extends SequenceMarker implements S return false; } - if (!equater(thisNext.value, thatNext.value)) { + if (!equater.equals(thisNext.value, thatNext.value)) { return false; } } @@ -123,7 +119,7 @@ export abstract class BaseSequence extends SequenceMarker implements S return new PrependSequence(this, obj); } - remove(obj: TElement, all?: boolean, equater?: EqualityComparison): Sequence { + remove(obj: TElement, all?: boolean, equater?: EqualityComparisonOrComparer): Sequence { return new RemoveSequence(this, obj, all, equater); } @@ -527,27 +523,27 @@ export abstract class BaseSequence extends SequenceMarker implements S return new OrderBySequence(this, true, selector, comparer); } - partition(equater?: EqualityComparison): Sequence> { + partition(equater?: EqualityComparisonOrComparer): Sequence> { return new PartitionSequence(this, equater); } - partitionBy(selector: Converter, equater?: EqualityComparison): Sequence> { + partitionBy(selector: Converter, equater?: EqualityComparisonOrComparer): Sequence> { return new PartitionBySequence(this, selector, equater); } - distinct(equater?: EqualityComparison): Sequence { + distinct(equater?: EqualityComparisonOrComparer): Sequence { return new DistinctSequence(this, equater); } - distinctBy(selector: Converter, equater?: EqualityComparison): Sequence { + distinctBy(selector: Converter, equater?: EqualityComparisonOrComparer): Sequence { return new DistinctBySequence(this, selector, equater); } - union(sequence: Iterable, equater?: EqualityComparison): Sequence { + union(sequence: Iterable, equater?: EqualityComparisonOrComparer): Sequence { return new UnionSequence(this, wrap(sequence), equater); } - unionBy(sequence: Iterable, selector: Converter, equater?: EqualityComparison): Sequence { + unionBy(sequence: Iterable, selector: Converter, equater?: EqualityComparisonOrComparer): Sequence { return new UnionBySequence(this, wrap(sequence), selector, equater); } @@ -833,29 +829,29 @@ export class DelegatedSequence extends SequenceMarker implements Seque return this.#sequence.where(predicate); } - groupBy(keySelector: Converter, elementSelector?: undefined, keyComparer?: EqualityComparison | undefined): Sequence>; - groupBy(keySelector: Converter, elementSelector: Converter, keyComparer?: EqualityComparison | undefined): Sequence>; + groupBy(keySelector: Converter, elementSelector?: undefined, keyComparer?: EqualityComparisonOrComparer | undefined): Sequence>; + groupBy(keySelector: Converter, elementSelector: Converter, keyComparer?: EqualityComparisonOrComparer | undefined): Sequence>; groupBy(keySelector: any, elementSelector?: any, keyComparer?: any) { return this.#sequence.groupBy(keySelector, elementSelector, keyComparer); } - join(sequence: Iterable, firstKeySelector: Converter, secondKeySelector: Converter, resultSelector?: undefined, keyComparer?: EqualityComparison | undefined): Sequence<[TElement, TOther]>; - join(sequence: Iterable, firstKeySelector: Converter, secondKeySelector: Converter, resultSelector: BiConverter, keyComparer?: EqualityComparison | undefined): Sequence; + join(sequence: Iterable, firstKeySelector: Converter, secondKeySelector: Converter, resultSelector?: undefined, keyComparer?: EqualityComparisonOrComparer | undefined): Sequence<[TElement, TOther]>; + join(sequence: Iterable, firstKeySelector: Converter, secondKeySelector: Converter, resultSelector: BiConverter, keyComparer?: EqualityComparisonOrComparer | undefined): Sequence; join(sequence: any, firstKeySelector: any, secondKeySelector: any, resultSelector?: any, keyComparer?: any) { return this.#sequence.join(sequence, firstKeySelector, secondKeySelector, resultSelector, keyComparer); } - groupJoin(sequence: Iterable, firstKeySelector: Converter, secondKeySelector: Converter, resultSelector?: undefined, keyComparer?: EqualityComparison | undefined): Sequence>; - groupJoin(sequence: Iterable, firstKeySelector: Converter, secondKeySelector: Converter, resultSelector: BiConverter, TResult>, keyComparer?: EqualityComparison | undefined): Sequence; + groupJoin(sequence: Iterable, firstKeySelector: Converter, secondKeySelector: Converter, resultSelector?: undefined, keyComparer?: EqualityComparisonOrComparer | undefined): Sequence>; + groupJoin(sequence: Iterable, firstKeySelector: Converter, secondKeySelector: Converter, resultSelector: BiConverter, TResult>, keyComparer?: EqualityComparisonOrComparer | undefined): Sequence; groupJoin(sequence: any, firstKeySelector: any, secondKeySelector: any, resultSelector?: any, keyComparer?: any) { return this.#sequence.groupJoin(sequence, firstKeySelector, secondKeySelector, resultSelector, keyComparer); } - contains(obj: TElement, equater?: EqualityComparison) { + contains(obj: TElement, equater?: EqualityComparisonOrComparer) { return this.#sequence.contains(obj, equater); } - sequenceEquals(sequence: Iterable, equater?: EqualityComparison) { + sequenceEquals(sequence: Iterable, equater?: EqualityComparisonOrComparer) { return this.#sequence.sequenceEquals(sequence, equater); } @@ -867,7 +863,7 @@ export class DelegatedSequence extends SequenceMarker implements Seque return this.#sequence.prepend(obj); } - remove(obj: TElement, all?: boolean, equater?: EqualityComparison) { + remove(obj: TElement, all?: boolean, equater?: EqualityComparisonOrComparer) { return this.#sequence.remove(obj, all, equater); } @@ -951,43 +947,43 @@ export class DelegatedSequence extends SequenceMarker implements Seque return this.#sequence.orderByDescending(selector, comparer); } - partition(equater?: EqualityComparison | undefined): Sequence> { + partition(equater?: EqualityComparisonOrComparer | undefined): Sequence> { return this.#sequence.partition(equater); } - partitionBy(selector: Converter, equater?: EqualityComparison | undefined): Sequence> { + partitionBy(selector: Converter, equater?: EqualityComparisonOrComparer | undefined): Sequence> { return this.#sequence.partitionBy(selector, equater); } - distinct(equater?: EqualityComparison) { + distinct(equater?: EqualityComparisonOrComparer) { return this.#sequence.distinct(equater); } - distinctBy(selector: Converter, equater?: EqualityComparison) { + distinctBy(selector: Converter, equater?: EqualityComparisonOrComparer) { return this.#sequence.distinctBy(selector, equater); } - union(sequence: Iterable, equater?: EqualityComparison) { + union(sequence: Iterable, equater?: EqualityComparisonOrComparer) { return this.#sequence.union(sequence, equater); } - unionBy(sequence: Iterable, selector: Converter, equater?: EqualityComparison) { + unionBy(sequence: Iterable, selector: Converter, equater?: EqualityComparisonOrComparer) { return this.#sequence.unionBy(sequence, selector, equater); } - except(sequence: Iterable, equater?: EqualityComparison) { + except(sequence: Iterable, equater?: EqualityComparisonOrComparer) { return this.#sequence.except(sequence, equater); } - exceptBy(sequence: Iterable, selector: Converter, equater?: EqualityComparison) { + exceptBy(sequence: Iterable, selector: Converter, equater?: EqualityComparisonOrComparer) { return this.#sequence.exceptBy(sequence, selector, equater); } - intersect(sequence: Iterable, equater?: EqualityComparison) { + intersect(sequence: Iterable, equater?: EqualityComparisonOrComparer) { return this.#sequence.intersect(sequence, equater); } - intersectBy(sequence: Iterable, selector: Converter, equater?: EqualityComparison) { + intersectBy(sequence: Iterable, selector: Converter, equater?: EqualityComparisonOrComparer) { return this.#sequence.intersectBy(sequence, selector, equater); } @@ -1370,9 +1366,10 @@ export class WrappedArray extends BaseSequence { return this.#array.length; } - override contains(obj: T, equater?: EqualityComparison): boolean { + override contains(obj: T, equater?: EqualityComparisonOrComparer): boolean { if (equater) { - return this.#array.some(x => equater(x, obj)); + const equalityComparer = asEqualityComparer(equater); + return this.#array.some(x => equalityComparer.equals(x, obj)); } return this.#array.includes(obj); @@ -1466,7 +1463,7 @@ export class WrappedSet extends BaseSequence { return this.#set.size; } - override contains(obj: T, equater?: EqualityComparison) { + override contains(obj: T, equater?: EqualityComparisonOrComparer) { if (equater) { return super.contains(obj, equater); } @@ -1496,7 +1493,7 @@ export class WrappedMap extends BaseSequence<[K, V]> { return this.#map.size; } - override contains(obj: [K, V], equater?: EqualityComparison<[K, V]>) { + override contains(obj: [K, V], equater?: EqualityComparisonOrComparer<[K, V]>) { if (equater) { return super.contains(obj, equater); } @@ -1605,9 +1602,9 @@ export class ConcatSequence extends BaseSequence { class DistinctSequence extends BaseSequence { readonly #sequence: Sequence; - readonly #equater: EqualityComparison | undefined; + readonly #equater: EqualityComparisonOrComparer | undefined; - constructor(sequence: Sequence, equater?: EqualityComparison) { + constructor(sequence: Sequence, equater?: EqualityComparisonOrComparer) { super(); this.#sequence = sequence; @@ -1632,9 +1629,9 @@ class DistinctSequence extends BaseSequence { class DistinctBySequence extends BaseSequence { readonly #sequence: Sequence; readonly #converter: Converter; - readonly #equater: EqualityComparison | undefined; + readonly #equater: EqualityComparisonOrComparer | undefined; - constructor(sequence: Sequence, converter: Converter, equater?: EqualityComparison) { + constructor(sequence: Sequence, converter: Converter, equater?: EqualityComparisonOrComparer) { super(); this.#sequence = sequence; @@ -2100,9 +2097,9 @@ export class ZippedSequence extends BaseSequence<[T, U]> { class UnionSequence extends BaseSequence { readonly #first: Sequence; readonly #second: Sequence; - readonly #equater: EqualityComparison | undefined; + readonly #equater: EqualityComparisonOrComparer | undefined; - constructor(first: Sequence, second: Sequence, equater?: EqualityComparison) { + constructor(first: Sequence, second: Sequence, equater?: EqualityComparisonOrComparer) { super(); this.#first = first; @@ -2134,9 +2131,9 @@ class UnionBySequence extends BaseSequence { readonly #first: Sequence; readonly #second: Sequence; readonly #selector: Converter; - readonly #equater: EqualityComparison | undefined; + readonly #equater: EqualityComparisonOrComparer | undefined; - constructor(first: Sequence, second: Sequence, selector: Converter, equater?: EqualityComparison) { + constructor(first: Sequence, second: Sequence, selector: Converter, equater?: EqualityComparisonOrComparer) { super(); this.#first = first; @@ -2168,9 +2165,9 @@ class UnionBySequence extends BaseSequence { class ExceptSequence extends BaseSequence { readonly #first: Sequence; readonly #second: Sequence; - readonly #equater: EqualityComparison | undefined; + readonly #equater: EqualityComparisonOrComparer | undefined; - constructor(first: Sequence, second: Sequence, equater?: EqualityComparison) { + constructor(first: Sequence, second: Sequence, equater?: EqualityComparisonOrComparer) { super(); this.#first = first; @@ -2201,9 +2198,9 @@ class ExceptBySequence extends BaseSequence { readonly #first: Sequence; readonly #second: Sequence; readonly #selector: Converter; - readonly #equater: EqualityComparison | undefined; + readonly #equater: EqualityComparisonOrComparer | undefined; - constructor(first: Sequence, second: Sequence, selector: Converter, equater?: EqualityComparison) { + constructor(first: Sequence, second: Sequence, selector: Converter, equater?: EqualityComparisonOrComparer) { super(); this.#first = first; @@ -2234,9 +2231,9 @@ class ExceptBySequence extends BaseSequence { class IntersectSequence extends BaseSequence { readonly #first: Sequence; readonly #second: Sequence; - readonly #equater: EqualityComparison | undefined; + readonly #equater: EqualityComparisonOrComparer | undefined; - constructor(first: Sequence, second: Sequence, equater?: EqualityComparison) { + constructor(first: Sequence, second: Sequence, equater?: EqualityComparisonOrComparer) { super(); this.#first = first; @@ -2265,9 +2262,9 @@ class IntersectBySequence extends BaseSequence { readonly #first: Sequence; readonly #second: Sequence; readonly #selector: Converter; - readonly #equater: EqualityComparison | undefined; + readonly #equater: EqualityComparisonOrComparer | undefined; - constructor(first: Sequence, second: Sequence, selector: Converter, equater?: EqualityComparison) { + constructor(first: Sequence, second: Sequence, selector: Converter, equater?: EqualityComparisonOrComparer) { super(); this.#first = first; @@ -2329,9 +2326,9 @@ class GroupBySequence extends BaseSequence; readonly #keySelector: Converter; readonly #elementSelector: Converter; - readonly #keyEquater: EqualityComparison | undefined; + readonly #keyEquater: EqualityComparisonOrComparer | undefined; - constructor(sequence: Sequence, keySelector: Converter, elementSelector?: Converter, keyEquater?: EqualityComparison) { + constructor(sequence: Sequence, keySelector: Converter, elementSelector?: Converter, keyEquater?: EqualityComparisonOrComparer) { super(); this.#sequence = sequence; @@ -2448,9 +2445,9 @@ class JoinSequence extends BaseSequence readonly #firstKeySelector: Converter; readonly #secondKeySelector: Converter; readonly #resultSelector: BiConverter; - readonly #keyEquater: EqualityComparison; + readonly #keyEquater: EqualityComparer; - constructor(first: Sequence, second: Sequence, firstKeySelector: Converter, secondKeySelector: Converter, resultSelector?: BiConverter, keyEquater?: EqualityComparison) { + constructor(first: Sequence, second: Sequence, firstKeySelector: Converter, secondKeySelector: Converter, resultSelector?: BiConverter, keyEquater?: EqualityComparisonOrComparer) { super(); this.#first = first; @@ -2458,7 +2455,7 @@ class JoinSequence extends BaseSequence this.#firstKeySelector = firstKeySelector; this.#secondKeySelector = secondKeySelector; this.#resultSelector = resultSelector ?? JoinSequence.#defaultResultSelector as BiConverter; - this.#keyEquater = keyEquater ?? strictEquals; + this.#keyEquater = keyEquater ? asEqualityComparer(keyEquater) : defaultEqualityComparer; } static #defaultResultSelector(first: TOuter, second: TInner): [TOuter, TInner] { @@ -2476,7 +2473,7 @@ class JoinSequence extends BaseSequence for (const secondObj of this.#second) { const secondKey = this.#secondKeySelector(secondObj); - if (this.#keyEquater(firstKey, secondKey)) { + if (this.#keyEquater.equals(firstKey, secondKey)) { yield this.#resultSelector(firstObj, secondObj); } } @@ -2490,9 +2487,9 @@ class GroupJoinSequence extends BaseSequence; readonly #secondKeySelector: Converter; readonly #resultSelector: BiConverter, TResult>; - readonly #keyEquater: EqualityComparison; + readonly #keyEquater: EqualityComparer; - constructor(first: Sequence, second: Sequence, firstKeySelector: Converter, secondKeySelector: Converter, resultSelector?: BiConverter, TResult>, keyEquater?: EqualityComparison) { + constructor(first: Sequence, second: Sequence, firstKeySelector: Converter, secondKeySelector: Converter, resultSelector?: BiConverter, TResult>, keyEquater?: EqualityComparisonOrComparer) { super(); this.#first = first; @@ -2500,7 +2497,7 @@ class GroupJoinSequence extends BaseSequence, TResult>; - this.#keyEquater = keyEquater ?? strictEquals; + this.#keyEquater = keyEquater ? asEqualityComparer(keyEquater) : defaultEqualityComparer; } static #defaultResultSelector(first: TOuter, second: Sequence) { @@ -2523,7 +2520,7 @@ class GroupJoinSequence extends BaseSequence extends BaseSequence { readonly #sequence: Sequence; readonly #obj: T; readonly #all: boolean; - readonly #equater: EqualityComparison; + readonly #equater: EqualityComparer; - constructor(sequence: Sequence, obj: T, all?: boolean, equater?: EqualityComparison) { + constructor(sequence: Sequence, obj: T, all?: boolean, equater?: EqualityComparisonOrComparer) { super(); this.#sequence = sequence; this.#obj = obj; this.#all = all ?? false; - this.#equater = equater ?? strictEquals; + this.#equater = equater ? asEqualityComparer(equater) : defaultEqualityComparer; } override maxCount() { @@ -2556,7 +2553,7 @@ class RemoveSequence extends BaseSequence { let gotOne = false; for (const obj of this.#sequence) { - if (this.#equater(this.#obj, obj)) { + if (this.#equater.equals(this.#obj, obj)) { if (this.#all) { continue; } @@ -2600,13 +2597,13 @@ class CacheSequence extends BaseSequence { class PartitionSequence extends BaseSequence> { readonly #sequence: Sequence; - readonly #equater: EqualityComparison; + readonly #equater: EqualityComparisonOrComparer | undefined; - constructor(sequence: Sequence, equater: EqualityComparison | undefined) { + constructor(sequence: Sequence, equater: EqualityComparisonOrComparer | undefined) { super(); this.#sequence = sequence; - this.#equater = equater ?? strictEquals; + this.#equater = equater; } override *iterator() { @@ -2631,14 +2628,14 @@ class PartitionSequence extends BaseSequence> { class PartitionBySequence extends BaseSequence> { readonly #sequence: Sequence; readonly #selector: Converter; - readonly #equater: EqualityComparison; + readonly #equater: EqualityComparisonOrComparer | undefined; - constructor(sequence: Sequence, selector: Converter, equater: EqualityComparison | undefined) { + constructor(sequence: Sequence, selector: Converter, equater: EqualityComparisonOrComparer | undefined) { super(); this.#sequence = sequence; this.#selector = selector; - this.#equater = equater ?? strictEquals; + this.#equater = equater; } override *iterator() { diff --git a/src/sync/types.ts b/src/sync/types.ts index bf791a3..b27bb0b 100644 --- a/src/sync/types.ts +++ b/src/sync/types.ts @@ -1,7 +1,7 @@ import { AsyncSequence } from "../async/types.js"; import { Collector } from "../collector/types.js"; import { ComparisonOrComparer, Comparer } from "../comparer/types.js"; -import { EqualityComparison } from "../equality-comparer/types.js"; +import { EqualityComparisonOrComparer } from "../equality-comparer/types.js"; import { RandomOptions } from "../random/types.js"; import { AnyPredicate, Converter, TypePredicate, BiConverter, Accumulator, Action } from "../types.js"; @@ -25,24 +25,24 @@ export interface Sequence extends Iterable { where(predicate: TypePredicate): Sequence; where(predicate: AnyPredicate): Sequence; - groupBy(keySelector: Converter, elementSelector?: undefined, keyComparer?: EqualityComparison): Sequence>; - groupBy(keySelector: Converter, elementSelector: Converter, keyComparer?: EqualityComparison): Sequence>; + groupBy(keySelector: Converter, elementSelector?: undefined, keyComparer?: EqualityComparisonOrComparer): Sequence>; + groupBy(keySelector: Converter, elementSelector: Converter, keyComparer?: EqualityComparisonOrComparer): Sequence>; - join(sequence: Iterable, firstKeySelector: Converter, secondKeySelector: Converter, resultSelector?: undefined, keyComparer?: EqualityComparison): Sequence<[TElement, TOther]>; - join(sequence: Iterable, firstKeySelector: Converter, secondKeySelector: Converter, resultSelector: BiConverter, keyComparer?: EqualityComparison): Sequence; + join(sequence: Iterable, firstKeySelector: Converter, secondKeySelector: Converter, resultSelector?: undefined, keyComparer?: EqualityComparisonOrComparer): Sequence<[TElement, TOther]>; + join(sequence: Iterable, firstKeySelector: Converter, secondKeySelector: Converter, resultSelector: BiConverter, keyComparer?: EqualityComparisonOrComparer): Sequence; - groupJoin(sequence: Iterable, firstKeySelector: Converter, secondKeySelector: Converter, resultSelector?: undefined, keyComparer?: EqualityComparison): Sequence>; - groupJoin(sequence: Iterable, firstKeySelector: Converter, secondKeySelector: Converter, resultSelector: BiConverter, TResult>, keyComparer?: EqualityComparison): Sequence; + groupJoin(sequence: Iterable, firstKeySelector: Converter, secondKeySelector: Converter, resultSelector?: undefined, keyComparer?: EqualityComparisonOrComparer): Sequence>; + groupJoin(sequence: Iterable, firstKeySelector: Converter, secondKeySelector: Converter, resultSelector: BiConverter, TResult>, keyComparer?: EqualityComparisonOrComparer): Sequence; - contains(obj: TElement, equater?: EqualityComparison): boolean; + contains(obj: TElement, equater?: EqualityComparisonOrComparer): boolean; - sequenceEquals(sequence: Iterable, equater?: EqualityComparison): boolean; + sequenceEquals(sequence: Iterable, equater?: EqualityComparisonOrComparer): boolean; append(obj: TElement): Sequence; prepend(obj: TElement): Sequence; - remove(obj: TElement, all?: boolean, equater?: EqualityComparison): Sequence; + remove(obj: TElement, all?: boolean, equater?: EqualityComparisonOrComparer): Sequence; concat(...sequences: Iterable[]): Sequence; @@ -77,20 +77,20 @@ export interface Sequence extends Iterable { orderDescending(comparer?: ComparisonOrComparer): OrderedSequence; orderByDescending(selector: Converter, comparer?: ComparisonOrComparer): OrderedSequence; - partition(equater?: EqualityComparison): Sequence>; - partitionBy(selector: Converter, equater?: EqualityComparison): Sequence>; + partition(equater?: EqualityComparisonOrComparer): Sequence>; + partitionBy(selector: Converter, equater?: EqualityComparisonOrComparer): Sequence>; - distinct(equater?: EqualityComparison): Sequence; - distinctBy(selector: Converter, equater?: EqualityComparison): Sequence; + distinct(equater?: EqualityComparisonOrComparer): Sequence; + distinctBy(selector: Converter, equater?: EqualityComparisonOrComparer): Sequence; - union(sequence: Iterable, equater?: EqualityComparison): Sequence; - unionBy(sequence: Iterable, selector: Converter, equater?: EqualityComparison): Sequence; + union(sequence: Iterable, equater?: EqualityComparisonOrComparer): Sequence; + unionBy(sequence: Iterable, selector: Converter, equater?: EqualityComparisonOrComparer): Sequence; - except(sequence: Iterable, equater?: EqualityComparison): Sequence; - exceptBy(sequence: Iterable, selector: Converter, equater?: EqualityComparison): Sequence; + except(sequence: Iterable, equater?: EqualityComparisonOrComparer): Sequence; + exceptBy(sequence: Iterable, selector: Converter, equater?: EqualityComparisonOrComparer): Sequence; - intersect(sequence: Iterable, equater?: EqualityComparison): Sequence; - intersectBy(sequence: Iterable, selector: Converter, equater?: EqualityComparison): Sequence; + intersect(sequence: Iterable, equater?: EqualityComparisonOrComparer): Sequence; + intersectBy(sequence: Iterable, selector: Converter, equater?: EqualityComparisonOrComparer): Sequence; all(predicate: AnyPredicate): boolean; any(predicate: AnyPredicate): boolean;