From 8639b664a1bfee00acc0bf3e6968e596b6fd7f4b Mon Sep 17 00:00:00 2001 From: "Afshin T. Darian" Date: Wed, 10 Aug 2022 12:38:08 +0100 Subject: [PATCH 01/62] Refactor some of the public API for iterators --- packages/algorithm/src/iter.ts | 82 ++++++---------------------------- 1 file changed, 13 insertions(+), 69 deletions(-) diff --git a/packages/algorithm/src/iter.ts b/packages/algorithm/src/iter.ts index 6d92fe045..84ff7f7a4 100644 --- a/packages/algorithm/src/iter.ts +++ b/packages/algorithm/src/iter.ts @@ -65,12 +65,6 @@ export interface IIterator extends IIterable { */ next(): T | undefined; } - -/** - * A type alias for an iterable or builtin array-like object. - */ -export type IterableOrArrayLike = IIterable | ArrayLike; - /** * Create an iterator for an iterable object. * @@ -233,7 +227,7 @@ export function each( /** * Test whether all values in an iterable satisfy a predicate. * - * @param object - The iterable or array-like object of interest. + * @param object - The iterable object of interest. * * @param fn - The predicate function to invoke for each value. * @@ -256,14 +250,12 @@ export function each( * ``` */ export function every( - object: IterableOrArrayLike, - fn: (value: T, index: number) => boolean + object: Iterable, + fn: (value: T, index: number, object: Iterable) => boolean ): boolean { let index = 0; - let it = iter(object); - let value: T | undefined; - while ((value = it.next()) !== undefined) { - if (!fn(value, index++)) { + for (let value of object) { + if (false === fn(value, index++, object)) { return false; } } @@ -273,7 +265,7 @@ export function every( /** * Test whether any value in an iterable satisfies a predicate. * - * @param object - The iterable or array-like object of interest. + * @param object - The iterable object of interest. * * @param fn - The predicate function to invoke for each value. * @@ -296,14 +288,12 @@ export function every( * ``` */ export function some( - object: IterableOrArrayLike, - fn: (value: T, index: number) => boolean + object: Iterable, + fn: (value: T, index: number, object: Iterable) => boolean ): boolean { let index = 0; - let it = iter(object); - let value: T | undefined; - while ((value = it.next()) !== undefined) { - if (fn(value, index++)) { + for (let value of object) { + if (fn(value, index++, object)) { return true; } } @@ -313,58 +303,12 @@ export function some( /** * Create an array from an iterable of values. * - * @param object - The iterable or array-like object of interest. + * @param object - The iterable object of interest. * * @returns A new array of values from the given object. - * - * #### Example - * ```typescript - * import { iter, toArray } from '@lumino/algorithm'; - * - * let data = [1, 2, 3, 4, 5, 6]; - * - * let stream = iter(data); - * - * toArray(stream); // [1, 2, 3, 4, 5, 6]; - * ``` */ -export function toArray(object: IterableOrArrayLike): T[] { - let index = 0; - let result: T[] = []; - let it = iter(object); - let value: T | undefined; - while ((value = it.next()) !== undefined) { - result[index++] = value; - } - return result; -} - -/** - * Create an object from an iterable of key/value pairs. - * - * @param object - The iterable or array-like object of interest. - * - * @returns A new object mapping keys to values. - * - * #### Example - * ```typescript - * import { toObject } from '@lumino/algorithm'; - * - * let data = [['one', 1], ['two', 2], ['three', 3]]; - * - * toObject(data); // { one: 1, two: 2, three: 3 } - * ``` - */ -export function toObject(object: IterableOrArrayLike<[string, T]>): { - [key: string]: T; -} { - let it = iter(object); - let pair: [string, T] | undefined; - let result: { [key: string]: T } = {}; - while ((pair = it.next()) !== undefined) { - result[pair[0]] = pair[1]; - } - return result; +export function toArray(object: Iterable): T[] { + return [...object]; } /** From a935f6a672d82a1dcaad170038a83cd82e1f12d9 Mon Sep 17 00:00:00 2001 From: "Afshin T. Darian" Date: Wed, 10 Aug 2022 13:30:00 +0100 Subject: [PATCH 02/62] More iterator refactoring --- packages/algorithm/src/iter.ts | 179 --------------------------------- 1 file changed, 179 deletions(-) diff --git a/packages/algorithm/src/iter.ts b/packages/algorithm/src/iter.ts index 84ff7f7a4..b1dff0a40 100644 --- a/packages/algorithm/src/iter.ts +++ b/packages/algorithm/src/iter.ts @@ -8,185 +8,6 @@ | The full license is in the file LICENSE, distributed with this software. |----------------------------------------------------------------------------*/ -/** - * An object which can produce an iterator over its values. - */ -export interface IIterable { - /** - * Get an iterator over the object's values. - * - * @returns An iterator which yields the object's values. - * - * #### Notes - * Depending on the iterable, the returned iterator may or may not be - * a new object. A collection or other container-like object should - * typically return a new iterator, while an iterator itself should - * normally return `this`. - */ - iter(): IIterator; -} - -/** - * An object which traverses a collection of values. - * - * #### Notes - * An `IIterator` is itself an `IIterable`. Most implementations of - * `IIterator` should simply return `this` from the `iter()` method. - */ -export interface IIterator extends IIterable { - /** - * Create an independent clone of the iterator. - * - * @returns A new independent clone of the iterator. - * - * #### Notes - * The cloned iterator can be consumed independently of the current - * iterator. In essence, it is a copy of the iterator value stream - * which starts at the current location. - * - * This can be useful for lookahead and stream duplication. - */ - clone(): IIterator; - - /** - * Get the next value from the iterator. - * - * @returns The next value from the iterator, or `undefined`. - * - * #### Notes - * The `undefined` value is used to signal the end of iteration and - * should therefore not be used as a value in a collection. - * - * The use of the `undefined` sentinel is an explicit design choice - * which favors performance over purity. The ES6 iterator design of - * returning a `{ value, done }` pair is suboptimal, as it requires - * an object allocation on each iteration; and an `isDone()` method - * would increase implementation and runtime complexity. - */ - next(): T | undefined; -} -/** - * Create an iterator for an iterable object. - * - * @param object - The iterable or array-like object of interest. - * - * @returns A new iterator for the given object. - * - * #### Notes - * This function allows iteration algorithms to operate on user-defined - * iterable types and builtin array-like objects in a uniform fashion. - */ -export function iter(object: IterableOrArrayLike): IIterator { - let it: IIterator; - if (typeof (object as any).iter === 'function') { - it = (object as IIterable).iter(); - } else { - it = new ArrayIterator(object as ArrayLike); - } - return it; -} - -/** - * Create an iterator for the keys in an object. - * - * @param object - The object of interest. - * - * @returns A new iterator for the keys in the given object. - * - * #### Complexity - * Linear. - * - * #### Example - * ```typescript - * import { each, keys } from '@lumino/algorithm'; - * - * let data = { one: 1, two: 2, three: 3 }; - * - * each(keys(data), key => { console.log(key); }); // 'one', 'two', 'three' - * ``` - */ -export function iterKeys(object: { - readonly [key: string]: T; -}): IIterator { - return new KeyIterator(object); -} - -/** - * Create an iterator for the values in an object. - * - * @param object - The object of interest. - * - * @returns A new iterator for the values in the given object. - * - * #### Complexity - * Linear. - * - * #### Example - * ```typescript - * import { each, values } from '@lumino/algorithm'; - * - * let data = { one: 1, two: 2, three: 3 }; - * - * each(values(data), value => { console.log(value); }); // 1, 2, 3 - * ``` - */ -export function iterValues(object: { - readonly [key: string]: T; -}): IIterator { - return new ValueIterator(object); -} - -/** - * Create an iterator for the items in an object. - * - * @param object - The object of interest. - * - * @returns A new iterator for the items in the given object. - * - * #### Complexity - * Linear. - * - * #### Example - * ```typescript - * import { each, items } from '@lumino/algorithm'; - * - * let data = { one: 1, two: 2, three: 3 }; - * - * each(items(data), value => { console.log(value); }); // ['one', 1], ['two', 2], ['three', 3] - * ``` - */ -export function iterItems(object: { - readonly [key: string]: T; -}): IIterator<[string, T]> { - return new ItemIterator(object); -} - -/** - * Create an iterator for an iterator-like function. - * - * @param fn - A function which behaves like an iterator `next` method. - * - * @returns A new iterator for the given function. - * - * #### Notes - * The returned iterator **cannot** be cloned. - * - * #### Example - * ```typescript - * import { each, iterFn } from '@lumino/algorithm'; - * - * let it = iterFn((() => { - * let i = 0; - * return () => i > 3 ? undefined : i++; - * })()); - * - * each(it, v => { console.log(v); }); // 0, 1, 2, 3 - * ``` - */ -export function iterFn(fn: () => T | undefined): IIterator { - return new FnIterator(fn); -} - /** * Invoke a function for each value in an iterable. * From 029bcc337a6ffafc692f850a68e351cb84cf6868 Mon Sep 17 00:00:00 2001 From: "Afshin T. Darian" Date: Wed, 10 Aug 2022 13:44:23 +0100 Subject: [PATCH 03/62] Update each() function --- packages/algorithm/src/iter.ts | 16 +++++++--------- 1 file changed, 7 insertions(+), 9 deletions(-) diff --git a/packages/algorithm/src/iter.ts b/packages/algorithm/src/iter.ts index b1dff0a40..562d1e709 100644 --- a/packages/algorithm/src/iter.ts +++ b/packages/algorithm/src/iter.ts @@ -11,7 +11,7 @@ /** * Invoke a function for each value in an iterable. * - * @param object - The iterable or array-like object of interest. + * @param object - The iterable object of interest. * * @param fn - The callback function to invoke for each value. * @@ -32,14 +32,12 @@ * ``` */ export function each( - object: IterableOrArrayLike, - fn: (value: T, index: number) => boolean | void + object: Iterable, + fn: (value: T, index: number, object: Iterable) => boolean | void ): void { let index = 0; - let it = iter(object); - let value: T | undefined; - while ((value = it.next()) !== undefined) { - if (fn(value, index++) === false) { + for (const value of object) { + if (false === fn(value, index++, object)) { return; } } @@ -75,7 +73,7 @@ export function every( fn: (value: T, index: number, object: Iterable) => boolean ): boolean { let index = 0; - for (let value of object) { + for (const value of object) { if (false === fn(value, index++, object)) { return false; } @@ -113,7 +111,7 @@ export function some( fn: (value: T, index: number, object: Iterable) => boolean ): boolean { let index = 0; - for (let value of object) { + for (const value of object) { if (fn(value, index++, object)) { return true; } From c88f20b2fbf4cebc7add5359a1c7b3c7afb8de8f Mon Sep 17 00:00:00 2001 From: "Afshin T. Darian" Date: Wed, 10 Aug 2022 14:32:24 +0100 Subject: [PATCH 04/62] Remove ArrayIterator --- packages/algorithm/src/iter.ts | 52 ---------------------------------- 1 file changed, 52 deletions(-) diff --git a/packages/algorithm/src/iter.ts b/packages/algorithm/src/iter.ts index 562d1e709..390bf8c5f 100644 --- a/packages/algorithm/src/iter.ts +++ b/packages/algorithm/src/iter.ts @@ -130,58 +130,6 @@ export function toArray(object: Iterable): T[] { return [...object]; } -/** - * An iterator for an array-like object. - * - * #### Notes - * This iterator can be used for any builtin JS array-like object. - */ -export class ArrayIterator implements IIterator { - /** - * Construct a new array iterator. - * - * @param source - The array-like object of interest. - */ - constructor(source: ArrayLike) { - this._source = source; - } - - /** - * Get an iterator over the object's values. - * - * @returns An iterator which yields the object's values. - */ - iter(): IIterator { - return this; - } - - /** - * Create an independent clone of the iterator. - * - * @returns A new independent clone of the iterator. - */ - clone(): IIterator { - let result = new ArrayIterator(this._source); - result._index = this._index; - return result; - } - - /** - * Get the next value from the iterator. - * - * @returns The next value from the iterator, or `undefined`. - */ - next(): T | undefined { - if (this._index >= this._source.length) { - return undefined; - } - return this._source[this._index++]; - } - - private _index = 0; - private _source: ArrayLike; -} - /** * An iterator for the keys in an object. * From f5176d6019d564953bee8ab14b513fe11da50b9f Mon Sep 17 00:00:00 2001 From: "Afshin T. Darian" Date: Wed, 10 Aug 2022 14:35:28 +0100 Subject: [PATCH 05/62] Remove KeyIterator, ValueIterator, ItemIterator, and FnIterator --- packages/algorithm/src/iter.ts | 232 --------------------------------- 1 file changed, 232 deletions(-) diff --git a/packages/algorithm/src/iter.ts b/packages/algorithm/src/iter.ts index 390bf8c5f..14cc0db0b 100644 --- a/packages/algorithm/src/iter.ts +++ b/packages/algorithm/src/iter.ts @@ -129,235 +129,3 @@ export function some( export function toArray(object: Iterable): T[] { return [...object]; } - -/** - * An iterator for the keys in an object. - * - * #### Notes - * This iterator can be used for any JS object. - */ -export class KeyIterator implements IIterator { - /** - * Construct a new key iterator. - * - * @param source - The object of interest. - * - * @param keys - The keys to iterate, if known. - */ - constructor( - source: { readonly [key: string]: any }, - keys = Object.keys(source) - ) { - this._source = source; - this._keys = keys; - } - - /** - * Get an iterator over the object's values. - * - * @returns An iterator which yields the object's values. - */ - iter(): IIterator { - return this; - } - - /** - * Create an independent clone of the iterator. - * - * @returns A new independent clone of the iterator. - */ - clone(): IIterator { - let result = new KeyIterator(this._source, this._keys); - result._index = this._index; - return result; - } - - /** - * Get the next value from the iterator. - * - * @returns The next value from the iterator, or `undefined`. - */ - next(): string | undefined { - if (this._index >= this._keys.length) { - return undefined; - } - let key = this._keys[this._index++]; - if (key in this._source) { - return key; - } - return this.next(); - } - - private _index = 0; - private _keys: string[]; - private _source: { readonly [key: string]: any }; -} - -/** - * An iterator for the values in an object. - * - * #### Notes - * This iterator can be used for any JS object. - */ -export class ValueIterator implements IIterator { - /** - * Construct a new value iterator. - * - * @param source - The object of interest. - * - * @param keys - The keys to iterate, if known. - */ - constructor( - source: { readonly [key: string]: T }, - keys = Object.keys(source) - ) { - this._source = source; - this._keys = keys; - } - - /** - * Get an iterator over the object's values. - * - * @returns An iterator which yields the object's values. - */ - iter(): IIterator { - return this; - } - - /** - * Create an independent clone of the iterator. - * - * @returns A new independent clone of the iterator. - */ - clone(): IIterator { - let result = new ValueIterator(this._source, this._keys); - result._index = this._index; - return result; - } - - /** - * Get the next value from the iterator. - * - * @returns The next value from the iterator, or `undefined`. - */ - next(): T | undefined { - if (this._index >= this._keys.length) { - return undefined; - } - let key = this._keys[this._index++]; - if (key in this._source) { - return this._source[key]; - } - return this.next(); - } - - private _index = 0; - private _keys: string[]; - private _source: { readonly [key: string]: T }; -} - -/** - * An iterator for the items in an object. - * - * #### Notes - * This iterator can be used for any JS object. - */ -export class ItemIterator implements IIterator<[string, T]> { - /** - * Construct a new item iterator. - * - * @param source - The object of interest. - * - * @param keys - The keys to iterate, if known. - */ - constructor( - source: { readonly [key: string]: T }, - keys = Object.keys(source) - ) { - this._source = source; - this._keys = keys; - } - - /** - * Get an iterator over the object's values. - * - * @returns An iterator which yields the object's values. - */ - iter(): IIterator<[string, T]> { - return this; - } - - /** - * Create an independent clone of the iterator. - * - * @returns A new independent clone of the iterator. - */ - clone(): IIterator<[string, T]> { - let result = new ItemIterator(this._source, this._keys); - result._index = this._index; - return result; - } - - /** - * Get the next value from the iterator. - * - * @returns The next value from the iterator, or `undefined`. - */ - next(): [string, T] | undefined { - if (this._index >= this._keys.length) { - return undefined; - } - let key = this._keys[this._index++]; - if (key in this._source) { - return [key, this._source[key]]; - } - return this.next(); - } - - private _index = 0; - private _keys: string[]; - private _source: { readonly [key: string]: T }; -} - -/** - * An iterator for an iterator-like function. - */ -export class FnIterator implements IIterator { - /** - * Construct a new function iterator. - * - * @param fn - The iterator-like function of interest. - */ - constructor(fn: () => T | undefined) { - this._fn = fn; - } - - /** - * Get an iterator over the object's values. - * - * @returns An iterator which yields the object's values. - */ - iter(): IIterator { - return this; - } - - /** - * Create an independent clone of the iterator. - * - * @returns A new independent clone of the iterator. - */ - clone(): IIterator { - throw new Error('An `FnIterator` cannot be cloned.'); - } - - /** - * Get the next value from the iterator. - * - * @returns The next value from the iterator, or `undefined`. - */ - next(): T | undefined { - return this._fn.call(undefined); - } - - private _fn: () => T | undefined; -} From 150738ac91bd3360a1bfb0970e350b6c789b1540 Mon Sep 17 00:00:00 2001 From: "Afshin T. Darian" Date: Wed, 10 Aug 2022 15:44:33 +0100 Subject: [PATCH 06/62] Remove zip() and ZipIterator --- packages/algorithm/src/index.ts | 1 - packages/algorithm/src/zip.ts | 86 ---------------------- packages/algorithm/tests/src/index.spec.ts | 1 - packages/algorithm/tests/src/zip.spec.ts | 42 ----------- 4 files changed, 130 deletions(-) delete mode 100644 packages/algorithm/src/zip.ts delete mode 100644 packages/algorithm/tests/src/zip.spec.ts diff --git a/packages/algorithm/src/index.ts b/packages/algorithm/src/index.ts index a5be3713d..c0f70e77b 100644 --- a/packages/algorithm/src/index.ts +++ b/packages/algorithm/src/index.ts @@ -23,4 +23,3 @@ export * from './sort'; export * from './stride'; export * from './string'; export * from './take'; -export * from './zip'; diff --git a/packages/algorithm/src/zip.ts b/packages/algorithm/src/zip.ts deleted file mode 100644 index 790dd74c7..000000000 --- a/packages/algorithm/src/zip.ts +++ /dev/null @@ -1,86 +0,0 @@ -// Copyright (c) Jupyter Development Team. -// Distributed under the terms of the Modified BSD License. -/*----------------------------------------------------------------------------- -| Copyright (c) 2014-2017, PhosphorJS Contributors -| -| Distributed under the terms of the BSD 3-Clause License. -| -| The full license is in the file LICENSE, distributed with this software. -|----------------------------------------------------------------------------*/ -import { IIterator, iter, IterableOrArrayLike } from './iter'; - -/** - * Iterate several iterables in lockstep. - * - * @param objects - The iterable or array-like objects of interest. - * - * @returns An iterator which yields successive tuples of values where - * each value is taken in turn from the provided iterables. It will - * be as long as the shortest provided iterable. - * - * #### Example - * ```typescript - * import { zip, toArray } from '@lumino/algorithm'; - * - * let data1 = [1, 2, 3]; - * let data2 = [4, 5, 6]; - * - * let stream = zip(data1, data2); - * - * toArray(stream); // [[1, 4], [2, 5], [3, 6]] - * ``` - */ -export function zip(...objects: IterableOrArrayLike[]): IIterator { - return new ZipIterator(objects.map(iter)); -} - -/** - * An iterator which iterates several sources in lockstep. - */ -export class ZipIterator implements IIterator { - /** - * Construct a new zip iterator. - * - * @param source - The iterators of interest. - */ - constructor(source: IIterator[]) { - this._source = source; - } - - /** - * Get an iterator over the object's values. - * - * @returns An iterator which yields the object's values. - */ - iter(): IIterator { - return this; - } - - /** - * Create an independent clone of the iterator. - * - * @returns A new independent clone of the iterator. - */ - clone(): IIterator { - return new ZipIterator(this._source.map(it => it.clone())); - } - - /** - * Get the next value from the iterator. - * - * @returns The next value from the iterator, or `undefined`. - */ - next(): T[] | undefined { - let result = new Array(this._source.length); - for (let i = 0, n = this._source.length; i < n; ++i) { - let value = this._source[i].next(); - if (value === undefined) { - return undefined; - } - result[i] = value; - } - return result; - } - - private _source: IIterator[]; -} diff --git a/packages/algorithm/tests/src/index.spec.ts b/packages/algorithm/tests/src/index.spec.ts index bbe99fce3..1abf2a5ef 100644 --- a/packages/algorithm/tests/src/index.spec.ts +++ b/packages/algorithm/tests/src/index.spec.ts @@ -22,4 +22,3 @@ import './sort.spec'; import './stride.spec'; import './string.spec'; import './take.spec'; -import './zip.spec'; diff --git a/packages/algorithm/tests/src/zip.spec.ts b/packages/algorithm/tests/src/zip.spec.ts deleted file mode 100644 index a6a071602..000000000 --- a/packages/algorithm/tests/src/zip.spec.ts +++ /dev/null @@ -1,42 +0,0 @@ -// Copyright (c) Jupyter Development Team. -// Distributed under the terms of the Modified BSD License. -/*----------------------------------------------------------------------------- -| Copyright (c) 2014-2017, PhosphorJS Contributors -| -| Distributed under the terms of the BSD 3-Clause License. -| -| The full license is in the file LICENSE, distributed with this software. -|----------------------------------------------------------------------------*/ -import { iter, zip, ZipIterator } from '@lumino/algorithm'; - -import { testIterator } from './iter.spec'; - -describe('@lumino/algorithm', () => { - describe('zip()', () => { - testIterator(() => { - return [ - zip([1, 2, 3], [4, 5, 6]), - [ - [1, 4], - [2, 5], - [3, 6] - ] - ]; - }); - }); - - describe('ZipIterator', () => { - testIterator(() => { - let i1 = iter(['one', 'two']); - let i2 = iter([1, 2]); - let i3 = iter([true, false]); - type T = string | number | boolean; - let it = new ZipIterator([i1, i2, i3]); - let results = [ - ['one', 1, true], - ['two', 2, false] - ]; - return [it, results]; - }); - }); -}); From ddeab324f665d1b3961fefb6527322f44e2e67bc Mon Sep 17 00:00:00 2001 From: "Afshin T. Darian" Date: Wed, 10 Aug 2022 16:23:11 +0100 Subject: [PATCH 07/62] Remove take() and TakeIterator --- packages/algorithm/src/index.ts | 1 - packages/algorithm/src/take.ts | 86 ---------------------- packages/algorithm/tests/src/index.spec.ts | 1 - packages/algorithm/tests/src/take.spec.ts | 26 ------- 4 files changed, 114 deletions(-) delete mode 100644 packages/algorithm/src/take.ts delete mode 100644 packages/algorithm/tests/src/take.spec.ts diff --git a/packages/algorithm/src/index.ts b/packages/algorithm/src/index.ts index c0f70e77b..e6f1f56f6 100644 --- a/packages/algorithm/src/index.ts +++ b/packages/algorithm/src/index.ts @@ -22,4 +22,3 @@ export * from './retro'; export * from './sort'; export * from './stride'; export * from './string'; -export * from './take'; diff --git a/packages/algorithm/src/take.ts b/packages/algorithm/src/take.ts deleted file mode 100644 index cccd4021d..000000000 --- a/packages/algorithm/src/take.ts +++ /dev/null @@ -1,86 +0,0 @@ -// Copyright (c) Jupyter Development Team. -// Distributed under the terms of the Modified BSD License. -/*----------------------------------------------------------------------------- -| Copyright (c) 2014-2017, PhosphorJS Contributors -| -| Distributed under the terms of the BSD 3-Clause License. -| -| The full license is in the file LICENSE, distributed with this software. -|----------------------------------------------------------------------------*/ -import { IIterator, iter, IterableOrArrayLike } from './iter'; - -/** - * Take a fixed number of items from an iterable. - * - * @param object - The iterable or array-like object of interest. - * - * @param count - The number of items to take from the iterable. - * - * @returns An iterator which yields the specified number of items - * from the source iterable. - * - * #### Notes - * The returned iterator will exhaust early if the source iterable - * contains an insufficient number of items. - */ -export function take( - object: IterableOrArrayLike, - count: number -): IIterator { - return new TakeIterator(iter(object), count); -} - -/** - * An iterator which takes a fixed number of items from a source. - */ -export class TakeIterator implements IIterator { - /** - * Construct a new take iterator. - * - * @param source - The iterator of interest. - * - * @param count - The number of items to take from the source. - */ - constructor(source: IIterator, count: number) { - this._source = source; - this._count = count; - } - - /** - * Get an iterator over the object's values. - * - * @returns An iterator which yields the object's values. - */ - iter(): IIterator { - return this; - } - - /** - * Create an independent clone of the iterator. - * - * @returns A new independent clone of the iterator. - */ - clone(): IIterator { - return new TakeIterator(this._source.clone(), this._count); - } - - /** - * Get the next value from the iterator. - * - * @returns The next value from the iterator, or `undefined`. - */ - next(): T | undefined { - if (this._count <= 0) { - return undefined; - } - let value = this._source.next(); - if (value === undefined) { - return undefined; - } - this._count--; - return value; - } - - private _count: number; - private _source: IIterator; -} diff --git a/packages/algorithm/tests/src/index.spec.ts b/packages/algorithm/tests/src/index.spec.ts index 1abf2a5ef..fc54c245c 100644 --- a/packages/algorithm/tests/src/index.spec.ts +++ b/packages/algorithm/tests/src/index.spec.ts @@ -21,4 +21,3 @@ import './retro.spec'; import './sort.spec'; import './stride.spec'; import './string.spec'; -import './take.spec'; diff --git a/packages/algorithm/tests/src/take.spec.ts b/packages/algorithm/tests/src/take.spec.ts deleted file mode 100644 index 9cb54e305..000000000 --- a/packages/algorithm/tests/src/take.spec.ts +++ /dev/null @@ -1,26 +0,0 @@ -// Copyright (c) Jupyter Development Team. -// Distributed under the terms of the Modified BSD License. -/*----------------------------------------------------------------------------- -| Copyright (c) 2014-2017, PhosphorJS Contributors -| -| Distributed under the terms of the BSD 3-Clause License. -| -| The full license is in the file LICENSE, distributed with this software. -|----------------------------------------------------------------------------*/ -import { iter, take, TakeIterator } from '@lumino/algorithm'; - -import { testIterator } from './iter.spec'; - -describe('@lumino/algorithm', () => { - describe('take()', () => { - testIterator(() => { - return [take([1, 2, 3, 4, 5], 2), [1, 2]]; - }); - }); - - describe('TakeIterator', () => { - testIterator(() => { - return [new TakeIterator(iter([0, 1, 2, 3]), 1), [0]]; - }); - }); -}); From ebc44cc5ea9385b46b8320e82cfb883399f82387 Mon Sep 17 00:00:00 2001 From: "Afshin T. Darian" Date: Wed, 10 Aug 2022 17:58:18 +0100 Subject: [PATCH 08/62] Remove toArray() --- packages/algorithm/src/iter.ts | 11 ----------- 1 file changed, 11 deletions(-) diff --git a/packages/algorithm/src/iter.ts b/packages/algorithm/src/iter.ts index 14cc0db0b..2d4eed70e 100644 --- a/packages/algorithm/src/iter.ts +++ b/packages/algorithm/src/iter.ts @@ -118,14 +118,3 @@ export function some( } return false; } - -/** - * Create an array from an iterable of values. - * - * @param object - The iterable object of interest. - * - * @returns A new array of values from the given object. - */ -export function toArray(object: Iterable): T[] { - return [...object]; -} From d40cc10a14470557499bcd5cfc5ca46f7d885921 Mon Sep 17 00:00:00 2001 From: "Afshin T. Darian" Date: Thu, 11 Aug 2022 00:42:23 +0100 Subject: [PATCH 09/62] Remove ChainIterator and reimplement chain() with native iterators --- packages/algorithm/src/chain.ts | 74 ++++----------------------------- 1 file changed, 8 insertions(+), 66 deletions(-) diff --git a/packages/algorithm/src/chain.ts b/packages/algorithm/src/chain.ts index a4c6bdda7..8e334ed83 100644 --- a/packages/algorithm/src/chain.ts +++ b/packages/algorithm/src/chain.ts @@ -7,90 +7,32 @@ | | The full license is in the file LICENSE, distributed with this software. |----------------------------------------------------------------------------*/ -import { IIterator, iter, IterableOrArrayLike } from './iter'; /** * Chain together several iterables. * - * @param objects - The iterable or array-like objects of interest. + * @param objects - The iterable objects of interest. * * @returns An iterator which yields the values of the iterables * in the order in which they are supplied. * * #### Example * ```typescript - * import { chain, toArray } from '@lumino/algorithm'; + * import { chain } from '@lumino/algorithm'; * * let data1 = [1, 2, 3]; * let data2 = [4, 5, 6]; * * let stream = chain(data1, data2); * - * toArray(stream); // [1, 2, 3, 4, 5, 6] + * Array.from(stream); // [1, 2, 3, 4, 5, 6] * ``` */ -export function chain(...objects: IterableOrArrayLike[]): IIterator { - return new ChainIterator(iter(objects.map(iter))); -} - -/** - * An iterator which chains together several iterators. - */ -export class ChainIterator implements IIterator { - /** - * Construct a new chain iterator. - * - * @param source - The iterator of iterators of interest. - */ - constructor(source: IIterator>) { - this._source = source; - this._active = undefined; - } - - /** - * Get an iterator over the object's values. - * - * @returns An iterator which yields the object's values. - */ - iter(): IIterator { - return this; - } - - /** - * Create an independent clone of the iterator. - * - * @returns A new independent clone of the iterator. - */ - clone(): IIterator { - let result = new ChainIterator(this._source.clone()); - result._active = this._active && this._active.clone(); - result._cloned = true; - this._cloned = true; - return result; - } - - /** - * Get the next value from the iterator. - * - * @returns The next value from the iterator, or `undefined`. - */ - next(): T | undefined { - if (this._active === undefined) { - let active = this._source.next(); - if (active === undefined) { - return undefined; - } - this._active = this._cloned ? active.clone() : active; - } - let value = this._active.next(); - if (value !== undefined) { - return value; +export function* chain(...objects: Iterable[]) { + for (const obj of objects) { + const it = obj[Symbol.iterator](); + for (let item = it.next(); !item.done; item = it.next()) { + yield item.value; } - this._active = undefined; - return this.next(); } - - private _source: IIterator>; - private _active: IIterator | undefined; - private _cloned = false; } From 77a44aecc27bb0d3ce1ee341a0d310b8a6c5d61c Mon Sep 17 00:00:00 2001 From: "Afshin T. Darian" Date: Thu, 11 Aug 2022 03:09:54 +0100 Subject: [PATCH 10/62] Remove RepeatIterator and reimplement repeat() and once() with native iterators --- packages/algorithm/src/repeat.ts | 70 +++++--------------------------- 1 file changed, 10 insertions(+), 60 deletions(-) diff --git a/packages/algorithm/src/repeat.ts b/packages/algorithm/src/repeat.ts index 4e2a30389..a2869cbd9 100644 --- a/packages/algorithm/src/repeat.ts +++ b/packages/algorithm/src/repeat.ts @@ -7,7 +7,6 @@ | | The full license is in the file LICENSE, distributed with this software. |----------------------------------------------------------------------------*/ -import { IIterator } from './iter'; /** * Create an iterator which repeats a value a number of times. @@ -20,15 +19,17 @@ import { IIterator } from './iter'; * * #### Example * ```typescript - * import { repeat, toArray } from '@lumino/algorithm'; + * import { repeat } from '@lumino/algorithm'; * * let stream = repeat(7, 3); * - * toArray(stream); // [7, 7, 7] + * Array.from(stream); // [7, 7, 7] * ``` */ -export function repeat(value: T, count: number): IIterator { - return new RepeatIterator(value, count); +export function* repeat(value: T, count: number) { + while (0 < count--) { + yield value; + } } /** @@ -40,64 +41,13 @@ export function repeat(value: T, count: number): IIterator { * * #### Example * ```typescript - * import { once, toArray } from '@lumino/algorithm'; + * import { once } from '@lumino/algorithm'; * * let stream = once(7); * - * toArray(stream); // [7] + * Array.from(stream); // [7] * ``` */ -export function once(value: T): IIterator { - return new RepeatIterator(value, 1); -} - -/** - * An iterator which repeats a value a specified number of times. - */ -export class RepeatIterator implements IIterator { - /** - * Construct a new repeat iterator. - * - * @param value - The value to repeat. - * - * @param count - The number of times to repeat the value. - */ - constructor(value: T, count: number) { - this._value = value; - this._count = count; - } - - /** - * Get an iterator over the object's values. - * - * @returns An iterator which yields the object's values. - */ - iter(): IIterator { - return this; - } - - /** - * Create an independent clone of the iterator. - * - * @returns A new independent clone of the iterator. - */ - clone(): IIterator { - return new RepeatIterator(this._value, this._count); - } - - /** - * Get the next value from the iterator. - * - * @returns The next value from the iterator, or `undefined`. - */ - next(): T | undefined { - if (this._count <= 0) { - return undefined; - } - this._count--; - return this._value; - } - - private _value: T; - private _count: number; +export function* once(value: T) { + yield value; } From d1b6e2ee71d96e1459610d327c645385af186c91 Mon Sep 17 00:00:00 2001 From: "Afshin T. Darian" Date: Thu, 11 Aug 2022 09:05:17 +0100 Subject: [PATCH 11/62] Reimplement take() with native iterators --- packages/algorithm/src/take.ts | 39 ++++++++++++++++++++++ packages/algorithm/tests/src/index.spec.ts | 1 + packages/algorithm/tests/src/take.spec.ts | 26 +++++++++++++++ 3 files changed, 66 insertions(+) create mode 100644 packages/algorithm/src/take.ts create mode 100644 packages/algorithm/tests/src/take.spec.ts diff --git a/packages/algorithm/src/take.ts b/packages/algorithm/src/take.ts new file mode 100644 index 000000000..4ac50d2fa --- /dev/null +++ b/packages/algorithm/src/take.ts @@ -0,0 +1,39 @@ +// Copyright (c) Jupyter Development Team. +// Distributed under the terms of the Modified BSD License. +/*----------------------------------------------------------------------------- +| Copyright (c) 2014-2017, PhosphorJS Contributors +| +| Distributed under the terms of the BSD 3-Clause License. +| +| The full license is in the file LICENSE, distributed with this software. +|----------------------------------------------------------------------------*/ + +/** + * Take a fixed number of items from an iterable. + * + * @param object - The iterable object of interest. + * + * @param count - The number of items to take from the iterable. + * + * @returns An iterator which yields the specified number of items + * from the source iterable. + * + * #### Notes + * The returned iterator will exhaust early if the source iterable + * contains an insufficient number of items. + * + * #### Example + * ```typescript + * import { take } from '@lumino/algorithm'; + * + * let stream = take([5, 4, 3, 2, 1, 0, -1], 3); + * + * Array.from(stream); // [5, 4, 3] + * ``` + */ +export function* take(object: Iterable, count: number) { + const it = object[Symbol.iterator](); + for (let item = it.next(); !item.done && 0 < count--; item = it.next()) { + yield item.value; + } +} diff --git a/packages/algorithm/tests/src/index.spec.ts b/packages/algorithm/tests/src/index.spec.ts index fc54c245c..1abf2a5ef 100644 --- a/packages/algorithm/tests/src/index.spec.ts +++ b/packages/algorithm/tests/src/index.spec.ts @@ -21,3 +21,4 @@ import './retro.spec'; import './sort.spec'; import './stride.spec'; import './string.spec'; +import './take.spec'; diff --git a/packages/algorithm/tests/src/take.spec.ts b/packages/algorithm/tests/src/take.spec.ts new file mode 100644 index 000000000..9cb54e305 --- /dev/null +++ b/packages/algorithm/tests/src/take.spec.ts @@ -0,0 +1,26 @@ +// Copyright (c) Jupyter Development Team. +// Distributed under the terms of the Modified BSD License. +/*----------------------------------------------------------------------------- +| Copyright (c) 2014-2017, PhosphorJS Contributors +| +| Distributed under the terms of the BSD 3-Clause License. +| +| The full license is in the file LICENSE, distributed with this software. +|----------------------------------------------------------------------------*/ +import { iter, take, TakeIterator } from '@lumino/algorithm'; + +import { testIterator } from './iter.spec'; + +describe('@lumino/algorithm', () => { + describe('take()', () => { + testIterator(() => { + return [take([1, 2, 3, 4, 5], 2), [1, 2]]; + }); + }); + + describe('TakeIterator', () => { + testIterator(() => { + return [new TakeIterator(iter([0, 1, 2, 3]), 1), [0]]; + }); + }); +}); From 4c13c6f6990263d234e0341160c86314c2aa227b Mon Sep 17 00:00:00 2001 From: "Afshin T. Darian" Date: Thu, 11 Aug 2022 10:32:44 +0100 Subject: [PATCH 12/62] Reimplment zip() with native iterators --- packages/algorithm/src/zip.ts | 39 ++++++++++++++++++++++ packages/algorithm/tests/src/zip.spec.ts | 42 ++++++++++++++++++++++++ 2 files changed, 81 insertions(+) create mode 100644 packages/algorithm/src/zip.ts create mode 100644 packages/algorithm/tests/src/zip.spec.ts diff --git a/packages/algorithm/src/zip.ts b/packages/algorithm/src/zip.ts new file mode 100644 index 000000000..c3f09fe7b --- /dev/null +++ b/packages/algorithm/src/zip.ts @@ -0,0 +1,39 @@ +// Copyright (c) Jupyter Development Team. +// Distributed under the terms of the Modified BSD License. +/*----------------------------------------------------------------------------- +| Copyright (c) 2014-2017, PhosphorJS Contributors +| +| Distributed under the terms of the BSD 3-Clause License. +| +| The full license is in the file LICENSE, distributed with this software. +|----------------------------------------------------------------------------*/ +import { every } from './iter'; + +/** + * Iterate several iterables in lockstep. + * + * @param objects - The iterable objects of interest. + * + * @returns An iterator which yields successive tuples of values where + * each value is taken in turn from the provided iterables. It will + * be as long as the shortest provided iterable. + * + * #### Example + * ```typescript + * import { zip } from '@lumino/algorithm'; + * + * let data1 = [1, 2, 3]; + * let data2 = [4, 5, 6]; + * + * let stream = zip(data1, data2); + * + * Array.from(stream); // [[1, 4], [2, 5], [3, 6]] + * ``` + */ +export function* zip(...objects: Iterable[]) { + const iters = objects.map(obj => obj[Symbol.iterator]()); + let tuple = iters.map(it => it.next()); + for (; every(tuple, item => !item.done); tuple = iters.map(it => it.next())) { + yield tuple.map(item => item.value); + } +} diff --git a/packages/algorithm/tests/src/zip.spec.ts b/packages/algorithm/tests/src/zip.spec.ts new file mode 100644 index 000000000..a6a071602 --- /dev/null +++ b/packages/algorithm/tests/src/zip.spec.ts @@ -0,0 +1,42 @@ +// Copyright (c) Jupyter Development Team. +// Distributed under the terms of the Modified BSD License. +/*----------------------------------------------------------------------------- +| Copyright (c) 2014-2017, PhosphorJS Contributors +| +| Distributed under the terms of the BSD 3-Clause License. +| +| The full license is in the file LICENSE, distributed with this software. +|----------------------------------------------------------------------------*/ +import { iter, zip, ZipIterator } from '@lumino/algorithm'; + +import { testIterator } from './iter.spec'; + +describe('@lumino/algorithm', () => { + describe('zip()', () => { + testIterator(() => { + return [ + zip([1, 2, 3], [4, 5, 6]), + [ + [1, 4], + [2, 5], + [3, 6] + ] + ]; + }); + }); + + describe('ZipIterator', () => { + testIterator(() => { + let i1 = iter(['one', 'two']); + let i2 = iter([1, 2]); + let i3 = iter([true, false]); + type T = string | number | boolean; + let it = new ZipIterator([i1, i2, i3]); + let results = [ + ['one', 1, true], + ['two', 2, false] + ]; + return [it, results]; + }); + }); +}); From 588e666d6198993188881eea51d07d1d6ffa3494 Mon Sep 17 00:00:00 2001 From: "Afshin T. Darian" Date: Thu, 11 Aug 2022 10:58:34 +0100 Subject: [PATCH 13/62] Reimplment stride() with native iterators --- packages/algorithm/src/stride.ts | 67 ++++---------------------------- 1 file changed, 8 insertions(+), 59 deletions(-) diff --git a/packages/algorithm/src/stride.ts b/packages/algorithm/src/stride.ts index 85cb44f2e..ec5cffe55 100644 --- a/packages/algorithm/src/stride.ts +++ b/packages/algorithm/src/stride.ts @@ -7,12 +7,11 @@ | | The full license is in the file LICENSE, distributed with this software. |----------------------------------------------------------------------------*/ -import { IIterator, iter, IterableOrArrayLike } from './iter'; /** * Iterate over an iterable using a stepped increment. * - * @param object - The iterable or array-like object of interest. + * @param object - The iterable object of interest. * * @param step - The distance to step on each iteration. A value * of less than `1` will behave the same as a value of `1`. @@ -21,70 +20,20 @@ import { IIterator, iter, IterableOrArrayLike } from './iter'; * * #### Example * ```typescript - * import { stride, toArray } from '@lumino/algorithm'; + * import { stride } from '@lumino/algorithm'; * * let data = [1, 2, 3, 4, 5, 6]; * * let stream = stride(data, 2); * - * toArray(stream); // [1, 3, 5]; + * Array.from(stream); // [1, 3, 5]; * ``` */ -export function stride( - object: IterableOrArrayLike, - step: number -): IIterator { - return new StrideIterator(iter(object), step); -} - -/** - * An iterator which traverses a source iterator step-wise. - */ -export class StrideIterator implements IIterator { - /** - * Construct a new stride iterator. - * - * @param source - The iterator of values of interest. - * - * @param step - The distance to step on each iteration. A value - * of less than `1` will behave the same as a value of `1`. - */ - constructor(source: IIterator, step: number) { - this._source = source; - this._step = step; - } - - /** - * Get an iterator over the object's values. - * - * @returns An iterator which yields the object's values. - */ - iter(): IIterator { - return this; - } - - /** - * Create an independent clone of the iterator. - * - * @returns A new independent clone of the iterator. - */ - clone(): IIterator { - return new StrideIterator(this._source.clone(), this._step); - } - - /** - * Get the next value from the iterator. - * - * @returns The next value from the iterator, or `undefined`. - */ - next(): T | undefined { - let value = this._source.next(); - for (let n = this._step - 1; n > 0; --n) { - this._source.next(); +export function* stride(object: Iterable, step: number) { + const it = object[Symbol.iterator](); + for (let count = 0, item = it.next(); !item.done; item = it.next()) { + if (0 === count++ % step) { + yield item.value; } - return value; } - - private _source: IIterator; - private _step: number; } From 346cd2a82e7628258d9a151159622947df13eb40 Mon Sep 17 00:00:00 2001 From: "Afshin T. Darian" Date: Thu, 11 Aug 2022 11:33:48 +0100 Subject: [PATCH 14/62] Update topologicSort() to accept native iterable --- packages/algorithm/src/sort.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/algorithm/src/sort.ts b/packages/algorithm/src/sort.ts index a1efdbc44..7456c5466 100644 --- a/packages/algorithm/src/sort.ts +++ b/packages/algorithm/src/sort.ts @@ -7,7 +7,7 @@ | | The full license is in the file LICENSE, distributed with this software. |----------------------------------------------------------------------------*/ -import { each, IterableOrArrayLike } from './iter'; +import { each } from './iter'; /** * Topologically sort an iterable of edges. @@ -35,7 +35,7 @@ import { each, IterableOrArrayLike } from './iter'; * topologicSort(data); // ['a', 'b', 'c', 'd', 'e'] * ``` */ -export function topologicSort(edges: IterableOrArrayLike<[T, T]>): T[] { +export function topologicSort(edges: Iterable<[T, T]>): T[] { // Setup the shared sorting state. let sorted: T[] = []; let visited = new Set(); From de3de596fd1c07f0f2ba1b804a5ec156d79a94a0 Mon Sep 17 00:00:00 2001 From: "Afshin T. Darian" Date: Thu, 11 Aug 2022 11:34:25 +0100 Subject: [PATCH 15/62] Reimplment retro() with native iterators --- packages/algorithm/src/retro.ts | 76 ++++----------------------------- 1 file changed, 9 insertions(+), 67 deletions(-) diff --git a/packages/algorithm/src/retro.ts b/packages/algorithm/src/retro.ts index 54e39eacb..29f823bc5 100644 --- a/packages/algorithm/src/retro.ts +++ b/packages/algorithm/src/retro.ts @@ -7,7 +7,6 @@ | | The full license is in the file LICENSE, distributed with this software. |----------------------------------------------------------------------------*/ -import { IIterator } from './iter'; /** * An object which can produce a reverse iterator over its values. @@ -18,14 +17,9 @@ export interface IRetroable { * * @returns An iterator which yields the object's values in reverse. */ - retro(): IIterator; + retro(): Iterator; } -/** - * A type alias for a retroable or builtin array-like object. - */ -export type RetroableOrArrayLike = IRetroable | ArrayLike; - /** * Create an iterator for a retroable object. * @@ -35,74 +29,22 @@ export type RetroableOrArrayLike = IRetroable | ArrayLike; * * #### Example * ```typescript - * import { retro, toArray } from '@lumino/algorithm'; + * import { retro } from '@lumino/algorithm'; * * let data = [1, 2, 3, 4, 5, 6]; * * let stream = retro(data); * - * toArray(stream); // [6, 5, 4, 3, 2, 1] + * Array.from(stream); // [6, 5, 4, 3, 2, 1] * ``` */ -export function retro(object: RetroableOrArrayLike): IIterator { - let it: IIterator; +export function retro(object: IRetroable | ArrayLike) { if (typeof (object as any).retro === 'function') { - it = (object as IRetroable).retro(); - } else { - it = new RetroArrayIterator(object as ArrayLike); - } - return it; -} - -/** - * An iterator which traverses an array-like object in reverse. - * - * #### Notes - * This iterator can be used for any builtin JS array-like object. - */ -export class RetroArrayIterator implements IIterator { - /** - * Construct a new retro iterator. - * - * @param source - The array-like object of interest. - */ - constructor(source: ArrayLike) { - this._source = source; - this._index = source.length - 1; - } - - /** - * Get an iterator over the object's values. - * - * @returns An iterator which yields the object's values. - */ - iter(): IIterator { - return this; - } - - /** - * Create an independent clone of the iterator. - * - * @returns A new independent clone of the iterator. - */ - clone(): IIterator { - let result = new RetroArrayIterator(this._source); - result._index = this._index; - return result; + return (object as IRetroable).retro(); } - - /** - * Get the next value from the iterator. - * - * @returns The next value from the iterator, or `undefined`. - */ - next(): T | undefined { - if (this._index < 0 || this._index >= this._source.length) { - return undefined; + return (function* () { + for (let index = (object as ArrayLike).length - 1; ~index; index--) { + yield (object as ArrayLike)[index]; } - return this._source[this._index--]; - } - - private _index: number; - private _source: ArrayLike; + })(); } From acaa6ed703d398fe66ce26675d254e12d323a407 Mon Sep 17 00:00:00 2001 From: "Afshin T. Darian" Date: Thu, 11 Aug 2022 13:44:53 +0100 Subject: [PATCH 16/62] Update reduce() to use native iterables --- packages/algorithm/src/reduce.ts | 33 ++++++++++++++++---------------- 1 file changed, 16 insertions(+), 17 deletions(-) diff --git a/packages/algorithm/src/reduce.ts b/packages/algorithm/src/reduce.ts index bfd754637..55341999f 100644 --- a/packages/algorithm/src/reduce.ts +++ b/packages/algorithm/src/reduce.ts @@ -7,12 +7,11 @@ | | The full license is in the file LICENSE, distributed with this software. |----------------------------------------------------------------------------*/ -import { iter, IterableOrArrayLike } from './iter'; /** * Summarize all values in an iterable using a reducer function. * - * @param object - The iterable or array-like object of interest. + * @param object - The iterable object of interest. * * @param fn - The reducer function to invoke for each value. * @@ -47,59 +46,59 @@ import { iter, IterableOrArrayLike } from './iter'; * ``` */ export function reduce( - object: IterableOrArrayLike, + object: Iterable, fn: (accumulator: T, value: T, index: number) => T ): T; export function reduce( - object: IterableOrArrayLike, + object: Iterable, fn: (accumulator: U, value: T, index: number) => U, initial: U ): U; export function reduce( - object: IterableOrArrayLike, + object: Iterable, fn: (accumulator: any, value: T, index: number) => any, initial?: unknown ): any { // Setup the iterator and fetch the first value. + const it = object[Symbol.iterator](); let index = 0; - let it = iter(object); let first = it.next(); // An empty iterator and no initial value is an error. - if (first === undefined && initial === undefined) { + if (first.done && initial === undefined) { throw new TypeError('Reduce of empty iterable with no initial value.'); } // If the iterator is empty, return the initial value. - if (first === undefined) { + if (first.done) { return initial; } // If the iterator has a single item and no initial value, the // reducer is not invoked and the first item is the return value. let second = it.next(); - if (second === undefined && initial === undefined) { - return first; + if (second.done && initial === undefined) { + return first.value; } // If iterator has a single item and an initial value is provided, // the reducer is invoked and that result is the return value. - if (second === undefined) { - return fn(initial, first, index++); + if (second.done) { + return fn(initial, first.value, index++); } // Setup the initial accumlated value. let accumulator: any; if (initial === undefined) { - accumulator = fn(first, second, index++); + accumulator = fn(first.value, second.value, index++); } else { - accumulator = fn(fn(initial, first, index++), second, index++); + accumulator = fn(fn(initial, first.value, index++), second.value, index++); } // Iterate the rest of the values, updating the accumulator. - let next: T | undefined; - while ((next = it.next()) !== undefined) { - accumulator = fn(accumulator, next, index++); + let next: IteratorResult; + while (!(next = it.next()).done) { + accumulator = fn(accumulator, next.value, index++); } // Return the final accumulated value. From fb48177915bb25cdaf8a45b7212cf94f11d600d9 Mon Sep 17 00:00:00 2001 From: "Afshin T. Darian" Date: Thu, 11 Aug 2022 14:54:51 +0100 Subject: [PATCH 17/62] Reimplment range() with native iterators --- packages/algorithm/src/range.ts | 94 +++++++-------------------------- 1 file changed, 19 insertions(+), 75 deletions(-) diff --git a/packages/algorithm/src/range.ts b/packages/algorithm/src/range.ts index ec2514698..cc314e31a 100644 --- a/packages/algorithm/src/range.ts +++ b/packages/algorithm/src/range.ts @@ -7,8 +7,6 @@ | | The full license is in the file LICENSE, distributed with this software. |----------------------------------------------------------------------------*/ -import { IIterator } from './iter'; - /** * Create an iterator of evenly spaced values. * @@ -26,78 +24,28 @@ import { IIterator } from './iter'; * * In the two argument form of `range(start, stop)`, `step` defaults * to `1`. + * + * #### Example + * ```typescript + * import { range } from '@lumino/algorithm'; + * + * let stream = range(2, 4); + * + * Array.from(stream); // [2, 3] + * ``` */ -export function range( - start: number, - stop?: number, - step?: number -): IIterator { +export function* range(start: number, stop?: number, step?: number) { if (stop === undefined) { - return new RangeIterator(0, start, 1); - } - if (step === undefined) { - return new RangeIterator(start, stop, 1); - } - return new RangeIterator(start, stop, step); -} - -/** - * An iterator which produces a range of evenly spaced values. - */ -export class RangeIterator implements IIterator { - /** - * Construct a new range iterator. - * - * @param start - The starting value for the range, inclusive. - * - * @param stop - The stopping value for the range, exclusive. - * - * @param step - The distance between each value. - */ - constructor(start: number, stop: number, step: number) { - this._start = start; - this._stop = stop; - this._step = step; - this._length = Private.rangeLength(start, stop, step); + stop = start; + start = 0; + step = 1; + } else if (step === undefined) { + step = 1; } - - /** - * Get an iterator over the object's values. - * - * @returns An iterator which yields the object's values. - */ - iter(): IIterator { - return this; + const length = Private.rangeLength(start, stop, step); + for (let index = 0; index < length; index++) { + yield start + step * index; } - - /** - * Create an independent clone of the iterator. - * - * @returns A new independent clone of the iterator. - */ - clone(): IIterator { - let result = new RangeIterator(this._start, this._stop, this._step); - result._index = this._index; - return result; - } - - /** - * Get the next value from the iterator. - * - * @returns The next value from the iterator, or `undefined`. - */ - next(): number | undefined { - if (this._index >= this._length) { - return undefined; - } - return this._start + this._step * this._index++; - } - - private _index = 0; - private _length: number; - private _start: number; - private _stop: number; - private _step: number; } /** @@ -115,11 +63,7 @@ namespace Private { * * @returns The number of steps need to traverse the range. */ - export function rangeLength( - start: number, - stop: number, - step: number - ): number { + export function rangeLength(start: number, stop: number, step: number) { if (step === 0) { return Infinity; } From e6964f363b354a8a4d6b6e94a39d705fa50ba993 Mon Sep 17 00:00:00 2001 From: "Afshin T. Darian" Date: Thu, 11 Aug 2022 15:53:04 +0100 Subject: [PATCH 18/62] Reimplement empty() with native iterators --- packages/algorithm/src/empty.ts | 42 ++++----------------------------- 1 file changed, 5 insertions(+), 37 deletions(-) diff --git a/packages/algorithm/src/empty.ts b/packages/algorithm/src/empty.ts index efa830f81..a7c580382 100644 --- a/packages/algorithm/src/empty.ts +++ b/packages/algorithm/src/empty.ts @@ -7,7 +7,6 @@ | | The full license is in the file LICENSE, distributed with this software. |----------------------------------------------------------------------------*/ -import { IIterator } from './iter'; /** * Create an empty iterator. @@ -16,45 +15,14 @@ import { IIterator } from './iter'; * * #### Example * ```typescript - * import { empty, toArray } from '@lumino/algorithm'; + * import { empty } from '@lumino/algorithm'; * * let stream = empty(); * - * toArray(stream); // [] + * Array.from(stream); // [] * ``` */ -export function empty(): IIterator { - return new EmptyIterator(); -} - -/** - * An iterator which is always empty. - */ -export class EmptyIterator implements IIterator { - /** - * Get an iterator over the object's values. - * - * @returns An iterator which yields the object's values. - */ - iter(): IIterator { - return this; - } - - /** - * Create an independent clone of the iterator. - * - * @returns A new independent clone of the iterator. - */ - clone(): IIterator { - return new EmptyIterator(); - } - - /** - * Get the next value from the iterator. - * - * @returns The next value from the iterator, or `undefined`. - */ - next(): T | undefined { - return undefined; - } +// eslint-disable-next-line require-yield, @typescript-eslint/no-unused-vars +export function* empty() { + return; } From 462f495de1d1b1586bddf9c4608fa5ea69c61f21 Mon Sep 17 00:00:00 2001 From: "Afshin T. Darian" Date: Thu, 11 Aug 2022 16:08:54 +0100 Subject: [PATCH 19/62] Reimplement filter() with native interators --- packages/algorithm/src/filter.ts | 74 +++++--------------------------- 1 file changed, 10 insertions(+), 64 deletions(-) diff --git a/packages/algorithm/src/filter.ts b/packages/algorithm/src/filter.ts index 0c85ba9bf..2eee493f9 100644 --- a/packages/algorithm/src/filter.ts +++ b/packages/algorithm/src/filter.ts @@ -7,12 +7,11 @@ | | The full license is in the file LICENSE, distributed with this software. |----------------------------------------------------------------------------*/ -import { IIterator, iter, IterableOrArrayLike } from './iter'; /** * Filter an iterable for values which pass a test. * - * @param object - The iterable or array-like object of interest. + * @param object - The iterable object of interest. * * @param fn - The predicate function to invoke for each value. * @@ -20,76 +19,23 @@ import { IIterator, iter, IterableOrArrayLike } from './iter'; * * #### Example * ```typescript - * import { filter, toArray } from '@lumino/algorithm'; + * import { filter } from '@lumino/algorithm'; * * let data = [1, 2, 3, 4, 5, 6]; * * let stream = filter(data, value => value % 2 === 0); * - * toArray(stream); // [2, 4, 6] + * Array.from(stream); // [2, 4, 6] * ``` */ -export function filter( - object: IterableOrArrayLike, +export function* filter( + object: Iterable, fn: (value: T, index: number) => boolean -): IIterator { - return new FilterIterator(iter(object), fn); -} - -/** - * An iterator which yields values which pass a test. - */ -export class FilterIterator implements IIterator { - /** - * Construct a new filter iterator. - * - * @param source - The iterator of values of interest. - * - * @param fn - The predicate function to invoke for each value. - */ - constructor(source: IIterator, fn: (value: T, index: number) => boolean) { - this._source = source; - this._fn = fn; - } - - /** - * Get an iterator over the object's values. - * - * @returns An iterator which yields the object's values. - */ - iter(): IIterator { - return this; - } - - /** - * Create an independent clone of the iterator. - * - * @returns A new independent clone of the iterator. - */ - clone(): IIterator { - let result = new FilterIterator(this._source.clone(), this._fn); - result._index = this._index; - return result; - } - - /** - * Get the next value from the iterator. - * - * @returns The next value from the iterator, or `undefined`. - */ - next(): T | undefined { - let fn = this._fn; - let it = this._source; - let value: T | undefined; - while ((value = it.next()) !== undefined) { - if (fn(value, this._index++)) { - return value; - } +) { + let index = 0; + for (const value of object) { + if (fn(value, index++)) { + yield value; } - return undefined; } - - private _index = 0; - private _source: IIterator; - private _fn: (value: T, index: number) => boolean; } From 6abfc62dbb3397fa61ae96eb5dd74392ea84fdc8 Mon Sep 17 00:00:00 2001 From: "Afshin T. Darian" Date: Thu, 11 Aug 2022 16:19:41 +0100 Subject: [PATCH 20/62] Reimplement map() with native interators --- packages/algorithm/src/map.ts | 71 +++++------------------------------ 1 file changed, 9 insertions(+), 62 deletions(-) diff --git a/packages/algorithm/src/map.ts b/packages/algorithm/src/map.ts index 6a8cd4cc7..575416993 100644 --- a/packages/algorithm/src/map.ts +++ b/packages/algorithm/src/map.ts @@ -7,12 +7,10 @@ | | The full license is in the file LICENSE, distributed with this software. |----------------------------------------------------------------------------*/ -import { IIterator, iter, IterableOrArrayLike } from './iter'; - /** * Transform the values of an iterable with a mapping function. * - * @param object - The iterable or array-like object of interest. + * @param object - The iterable object of interest. * * @param fn - The mapping function to invoke for each value. * @@ -20,72 +18,21 @@ import { IIterator, iter, IterableOrArrayLike } from './iter'; * * #### Example * ```typescript - * import { map, toArray } from '@lumino/algorithm'; + * import { map } from '@lumino/algorithm'; * * let data = [1, 2, 3]; * * let stream = map(data, value => value * 2); * - * toArray(stream); // [2, 4, 6] + * Array.from(stream); // [2, 4, 6] * ``` */ -export function map( - object: IterableOrArrayLike, +export function* map( + object: Iterable, fn: (value: T, index: number) => U -): IIterator { - return new MapIterator(iter(object), fn); -} - -/** - * An iterator which transforms values using a mapping function. - */ -export class MapIterator implements IIterator { - /** - * Construct a new map iterator. - * - * @param source - The iterator of values of interest. - * - * @param fn - The mapping function to invoke for each value. - */ - constructor(source: IIterator, fn: (value: T, index: number) => U) { - this._source = source; - this._fn = fn; - } - - /** - * Get an iterator over the object's values. - * - * @returns An iterator which yields the object's values. - */ - iter(): IIterator { - return this; - } - - /** - * Create an independent clone of the iterator. - * - * @returns A new independent clone of the iterator. - */ - clone(): IIterator { - let result = new MapIterator(this._source.clone(), this._fn); - result._index = this._index; - return result; - } - - /** - * Get the next value from the iterator. - * - * @returns The next value from the iterator, or `undefined`. - */ - next(): U | undefined { - let value = this._source.next(); - if (value === undefined) { - return undefined; - } - return this._fn.call(undefined, value, this._index++); +) { + let index = 0; + for (const value of object) { + yield fn(value, index++); } - - private _index = 0; - private _source: IIterator; - private _fn: (value: T, index: number) => U; } From 298ac8c7d371e942e1da0023390088c1d235d429 Mon Sep 17 00:00:00 2001 From: "Afshin T. Darian" Date: Thu, 11 Aug 2022 16:48:41 +0100 Subject: [PATCH 21/62] Update find(), findIndex(), min(), max(), and minmax() to use native types --- packages/algorithm/src/find.ts | 71 ++++++++++++++-------------------- 1 file changed, 28 insertions(+), 43 deletions(-) diff --git a/packages/algorithm/src/find.ts b/packages/algorithm/src/find.ts index dff870474..9751a98a7 100644 --- a/packages/algorithm/src/find.ts +++ b/packages/algorithm/src/find.ts @@ -7,12 +7,11 @@ | | The full license is in the file LICENSE, distributed with this software. |----------------------------------------------------------------------------*/ -import { iter, IterableOrArrayLike } from './iter'; /** * Find the first value in an iterable which matches a predicate. * - * @param object - The iterable or array-like object to search. + * @param object - The iterable object to search. * * @param fn - The predicate function to apply to the values. * @@ -42,13 +41,11 @@ import { iter, IterableOrArrayLike } from './iter'; * ``` */ export function find( - object: IterableOrArrayLike, + object: Iterable, fn: (value: T, index: number) => boolean ): T | undefined { let index = 0; - let it = iter(object); - let value: T | undefined; - while ((value = it.next()) !== undefined) { + for (const value of object) { if (fn(value, index++)) { return value; } @@ -59,7 +56,7 @@ export function find( /** * Find the index of the first value which matches a predicate. * - * @param object - The iterable or array-like object to search. + * @param object - The iterable object to search. * * @param fn - The predicate function to apply to the values. * @@ -89,13 +86,11 @@ export function find( * ``` */ export function findIndex( - object: IterableOrArrayLike, + object: Iterable, fn: (value: T, index: number) => boolean ): number { let index = 0; - let it = iter(object); - let value: T | undefined; - while ((value = it.next()) !== undefined) { + for (const value of object) { if (fn(value, index++)) { return index - 1; } @@ -106,7 +101,7 @@ export function findIndex( /** * Find the minimum value in an iterable. * - * @param object - The iterable or array-like object to search. + * @param object - The iterable object to search. * * @param fn - The 3-way comparison function to apply to the values. * It should return `< 0` if the first value is less than the second. @@ -132,17 +127,12 @@ export function findIndex( * ``` */ export function min( - object: IterableOrArrayLike, + object: Iterable, fn: (first: T, second: T) => number ): T | undefined { - let it = iter(object); - let value = it.next(); - if (value === undefined) { - return undefined; - } - let result = value; - while ((value = it.next()) !== undefined) { - if (fn(value, result) < 0) { + let result: T | undefined = undefined; + for (const value of object) { + if (fn(value, (result = result ?? value)) < 0) { result = value; } } @@ -152,7 +142,7 @@ export function min( /** * Find the maximum value in an iterable. * - * @param object - The iterable or array-like object to search. + * @param object - The iterable object to search. * * @param fn - The 3-way comparison function to apply to the values. * It should return `< 0` if the first value is less than the second. @@ -178,17 +168,12 @@ export function min( * ``` */ export function max( - object: IterableOrArrayLike, + object: Iterable, fn: (first: T, second: T) => number ): T | undefined { - let it = iter(object); - let value = it.next(); - if (value === undefined) { - return undefined; - } - let result = value; - while ((value = it.next()) !== undefined) { - if (fn(value, result) > 0) { + let result: T | undefined = undefined; + for (const value of object) { + if (fn(value, (result = result ?? value)) > 0) { result = value; } } @@ -198,7 +183,7 @@ export function max( /** * Find the minimum and maximum values in an iterable. * - * @param object - The iterable or array-like object to search. + * @param object - The iterable object to search. * * @param fn - The 3-way comparison function to apply to the values. * It should return `< 0` if the first value is less than the second. @@ -224,21 +209,21 @@ export function max( * ``` */ export function minmax( - object: IterableOrArrayLike, + object: Iterable, fn: (first: T, second: T) => number ): [T, T] | undefined { - let it = iter(object); - let value = it.next(); - if (value === undefined) { + const it = object[Symbol.iterator](); + let item = it.next(); + if (item.done) { return undefined; } - let vmin = value; - let vmax = value; - while ((value = it.next()) !== undefined) { - if (fn(value, vmin) < 0) { - vmin = value; - } else if (fn(value, vmax) > 0) { - vmax = value; + let vmin = item.value; + let vmax = item.value; + while (!(item = it.next()).done) { + if (fn(item.value, vmin) < 0) { + vmin = item.value; + } else if (fn(item.value, vmax) > 0) { + vmax = item.value; } } return [vmin, vmax]; From 93803402e14bbcc47cbce2d67cc039a03e72c3e7 Mon Sep 17 00:00:00 2001 From: "Afshin T. Darian" Date: Thu, 11 Aug 2022 16:56:44 +0100 Subject: [PATCH 22/62] Reimplement enumerate() with native types --- packages/algorithm/src/enumerate.ts | 65 +++-------------------------- 1 file changed, 6 insertions(+), 59 deletions(-) diff --git a/packages/algorithm/src/enumerate.ts b/packages/algorithm/src/enumerate.ts index 381498d47..998d2cc9e 100644 --- a/packages/algorithm/src/enumerate.ts +++ b/packages/algorithm/src/enumerate.ts @@ -7,12 +7,11 @@ | | The full license is in the file LICENSE, distributed with this software. |----------------------------------------------------------------------------*/ -import { IIterator, iter, IterableOrArrayLike } from './iter'; /** * Enumerate an iterable object. * - * @param object - The iterable or array-like object of interest. + * @param object - The iterable object of interest. * * @param start - The starting enum value. The default is `0`. * @@ -20,69 +19,17 @@ import { IIterator, iter, IterableOrArrayLike } from './iter'; * * #### Example * ```typescript - * import { enumerate, toArray } from '@lumino/algorithm'; + * import { enumerate } from '@lumino/algorithm'; * * let data = ['foo', 'bar', 'baz']; * * let stream = enumerate(data, 1); * - * toArray(stream); // [[1, 'foo'], [2, 'bar'], [3, 'baz']] + * Array.from(stream); // [[1, 'foo'], [2, 'bar'], [3, 'baz']] * ``` */ -export function enumerate( - object: IterableOrArrayLike, - start = 0 -): IIterator<[number, T]> { - return new EnumerateIterator(iter(object), start); -} - -/** - * An iterator which enumerates the source values. - */ -export class EnumerateIterator implements IIterator<[number, T]> { - /** - * Construct a new enumerate iterator. - * - * @param source - The iterator of values of interest. - * - * @param start - The starting enum value. - */ - constructor(source: IIterator, start: number) { - this._source = source; - this._index = start; - } - - /** - * Get an iterator over the object's values. - * - * @returns An iterator which yields the object's values. - */ - iter(): IIterator<[number, T]> { - return this; +export function* enumerate(object: Iterable, start = 0) { + for (const item of object) { + yield [start++, item]; } - - /** - * Create an independent clone of the iterator. - * - * @returns A new independent clone of the iterator. - */ - clone(): IIterator<[number, T]> { - return new EnumerateIterator(this._source.clone(), this._index); - } - - /** - * Get the next value from the iterator. - * - * @returns The next value from the iterator, or `undefined`. - */ - next(): [number, T] | undefined { - let value = this._source.next(); - if (value === undefined) { - return undefined; - } - return [this._index++, value]; - } - - private _source: IIterator; - private _index: number; } From ccbb6474dd6a7385fdaf87765769faf199be7f07 Mon Sep 17 00:00:00 2001 From: "Afshin T. Darian" Date: Thu, 11 Aug 2022 17:45:46 +0100 Subject: [PATCH 23/62] Fix algorithm package tests --- packages/algorithm/src/find.ts | 12 +++- packages/algorithm/src/index.ts | 2 + packages/algorithm/src/retro.ts | 6 +- packages/algorithm/tests/src/chain.spec.ts | 10 +-- packages/algorithm/tests/src/empty.spec.ts | 8 +-- packages/algorithm/tests/src/filter.spec.ts | 8 +-- packages/algorithm/tests/src/iter.spec.ts | 74 ++------------------- packages/algorithm/tests/src/map.spec.ts | 6 +- packages/algorithm/tests/src/range.spec.ts | 8 +-- packages/algorithm/tests/src/repeat.spec.ts | 10 +-- packages/algorithm/tests/src/retro.spec.ts | 10 +-- packages/algorithm/tests/src/stride.spec.ts | 6 +- packages/algorithm/tests/src/take.spec.ts | 6 +- packages/algorithm/tests/src/zip.spec.ts | 12 ++-- 14 files changed, 59 insertions(+), 119 deletions(-) diff --git a/packages/algorithm/src/find.ts b/packages/algorithm/src/find.ts index 9751a98a7..64caf1885 100644 --- a/packages/algorithm/src/find.ts +++ b/packages/algorithm/src/find.ts @@ -132,7 +132,11 @@ export function min( ): T | undefined { let result: T | undefined = undefined; for (const value of object) { - if (fn(value, (result = result ?? value)) < 0) { + if (result === undefined) { + result = value; + continue; + } + if (fn(value, result) < 0) { result = value; } } @@ -173,7 +177,11 @@ export function max( ): T | undefined { let result: T | undefined = undefined; for (const value of object) { - if (fn(value, (result = result ?? value)) > 0) { + if (result === undefined) { + result = value; + continue; + } + if (fn(value, result) > 0) { result = value; } } diff --git a/packages/algorithm/src/index.ts b/packages/algorithm/src/index.ts index e6f1f56f6..a5be3713d 100644 --- a/packages/algorithm/src/index.ts +++ b/packages/algorithm/src/index.ts @@ -22,3 +22,5 @@ export * from './retro'; export * from './sort'; export * from './stride'; export * from './string'; +export * from './take'; +export * from './zip'; diff --git a/packages/algorithm/src/retro.ts b/packages/algorithm/src/retro.ts index 29f823bc5..86f9b580d 100644 --- a/packages/algorithm/src/retro.ts +++ b/packages/algorithm/src/retro.ts @@ -17,7 +17,7 @@ export interface IRetroable { * * @returns An iterator which yields the object's values in reverse. */ - retro(): Iterator; + retro(): IterableIterator; } /** @@ -38,7 +38,9 @@ export interface IRetroable { * Array.from(stream); // [6, 5, 4, 3, 2, 1] * ``` */ -export function retro(object: IRetroable | ArrayLike) { +export function retro( + object: IRetroable | ArrayLike +): IterableIterator { if (typeof (object as any).retro === 'function') { return (object as IRetroable).retro(); } diff --git a/packages/algorithm/tests/src/chain.spec.ts b/packages/algorithm/tests/src/chain.spec.ts index 0761842c9..cefc857b3 100644 --- a/packages/algorithm/tests/src/chain.spec.ts +++ b/packages/algorithm/tests/src/chain.spec.ts @@ -7,7 +7,7 @@ | | The full license is in the file LICENSE, distributed with this software. |----------------------------------------------------------------------------*/ -import { chain, ChainIterator, iter } from '@lumino/algorithm'; +import { chain } from '@lumino/algorithm'; import { testIterator } from './iter.spec'; @@ -22,11 +22,11 @@ describe('@lumino/algorithm', () => { describe('ChainIterator', () => { testIterator(() => { - let a = iter([1, 2, 3]); - let b = iter(['four', 'five']); - let c = iter([true, false]); + let a = [1, 2, 3]; + let b = ['four', 'five']; + let c = [true, false][Symbol.iterator](); type T = number | string | boolean; - let it = new ChainIterator(iter([a, b, c])); + let it = chain(a, b, c); let expected = [1, 2, 3, 'four', 'five', true, false]; return [it, expected]; }); diff --git a/packages/algorithm/tests/src/empty.spec.ts b/packages/algorithm/tests/src/empty.spec.ts index 6c4f3627a..0159e6146 100644 --- a/packages/algorithm/tests/src/empty.spec.ts +++ b/packages/algorithm/tests/src/empty.spec.ts @@ -7,7 +7,7 @@ | | The full license is in the file LICENSE, distributed with this software. |----------------------------------------------------------------------------*/ -import { empty, EmptyIterator } from '@lumino/algorithm'; +import { empty } from '@lumino/algorithm'; import { testIterator } from './iter.spec'; @@ -17,10 +17,4 @@ describe('@lumino/algorithm', () => { return [empty(), []]; }); }); - - describe('EmptyIterator', () => { - testIterator(() => { - return [new EmptyIterator(), []]; - }); - }); }); diff --git a/packages/algorithm/tests/src/filter.spec.ts b/packages/algorithm/tests/src/filter.spec.ts index 51c3843a0..f5fbf1bc3 100644 --- a/packages/algorithm/tests/src/filter.spec.ts +++ b/packages/algorithm/tests/src/filter.spec.ts @@ -7,7 +7,7 @@ | | The full license is in the file LICENSE, distributed with this software. |----------------------------------------------------------------------------*/ -import { filter, FilterIterator, iter } from '@lumino/algorithm'; +import { filter } from '@lumino/algorithm'; import { testIterator } from './iter.spec'; @@ -21,11 +21,11 @@ describe('@lumino/algorithm', () => { }); }); - describe('FilterIterator', () => { + describe('filter()', () => { testIterator(() => { let expected = [1, 3, 5]; - let data = [0, 1, 2, 3, 4, 5]; - let it = new FilterIterator(iter(data), n => n % 2 !== 0); + let data = [0, 1, 2, 3, 4, 5][Symbol.iterator](); + let it = filter(data, n => n % 2 !== 0); return [it, expected]; }); }); diff --git a/packages/algorithm/tests/src/iter.spec.ts b/packages/algorithm/tests/src/iter.spec.ts index adb02697c..7bcbc70aa 100644 --- a/packages/algorithm/tests/src/iter.spec.ts +++ b/packages/algorithm/tests/src/iter.spec.ts @@ -9,20 +9,7 @@ |----------------------------------------------------------------------------*/ import { expect } from 'chai'; -import { - ArrayIterator, - each, - every, - IIterator, - iter, - some, - toArray -} from '@lumino/algorithm'; - -/** - * A factory which returns an iterator and expected results. - */ -export type IteratorFactory = () => [IIterator, T[]]; +import { each, every, some } from '@lumino/algorithm'; /** * A helper function to test the methods of an iterator. @@ -30,48 +17,18 @@ export type IteratorFactory = () => [IIterator, T[]]; * @param factory - A function which produces an iterator and the * expected results of that iterator. */ -export function testIterator(factory: IteratorFactory): void { - describe('iter()', () => { - it('should return `this` iterator', () => { - let [it] = factory(); - expect(it.iter()).to.equal(it); - }); - }); - - describe('clone()', () => { - it('should return a new independent iterator', () => { +export function testIterator( + factory: () => [IterableIterator, T[]] +): void { + describe('yield', () => { + it('should return the same values in the iterator', () => { let [it, results] = factory(); - let it2 = it.clone(); - expect(it).to.not.equal(it2); - expect(toArray(it)).to.deep.equal(results); - expect(toArray(it2)).to.deep.equal(results); - }); - }); - - describe('next()', () => { - it('should return the next value in the iterator', () => { - let value: T | undefined; - let [it, results] = factory(); - for (let i = 0; (value = it.next()) !== undefined; ++i) { - expect(value).to.deep.equal(results[i]); - } + expect(Array.from(it)).to.deep.equal(results); }); }); } describe('@lumino/algorithm', () => { - describe('iter()', () => { - it('should create an iterator for an array-like object', () => { - let data = [0, 1, 2, 3]; - expect(toArray(iter(data))).to.deep.equal(data); - }); - - it('should call `iter` on an iterable', () => { - let iterator = iter([1, 2, 3, 4]); - expect(iter(iterator)).to.equal(iterator); - }); - }); - describe('each()', () => { it('should visit every item in an iterable', () => { let result = 0; @@ -115,21 +72,4 @@ describe('@lumino/algorithm', () => { expect(invalid).to.equal(false); }); }); - - describe('toArray()', () => { - it('should create an array from an iterable', () => { - let data = [0, 1, 2, 3, 4, 5]; - let result = toArray(data); - expect(result).to.deep.equal(data); - expect(result).to.not.equal(data); - }); - }); - - describe('ArrayIterator', () => { - testIterator(() => { - let results = [1, 2, 3, 4, 5]; - let it = new ArrayIterator(results); - return [it, results]; - }); - }); }); diff --git a/packages/algorithm/tests/src/map.spec.ts b/packages/algorithm/tests/src/map.spec.ts index e9e658f38..f470513e8 100644 --- a/packages/algorithm/tests/src/map.spec.ts +++ b/packages/algorithm/tests/src/map.spec.ts @@ -7,7 +7,7 @@ | | The full license is in the file LICENSE, distributed with this software. |----------------------------------------------------------------------------*/ -import { iter, map, MapIterator } from '@lumino/algorithm'; +import { map } from '@lumino/algorithm'; import { testIterator } from './iter.spec'; @@ -20,10 +20,10 @@ describe('@lumino/algorithm', () => { }); }); - describe('MapIterator', () => { + describe('map()', () => { testIterator(() => { let result = [0, 1, 8, 27]; - let it = new MapIterator(iter([0, 1, 2, 3]), x => x ** 3); + let it = map([0, 1, 2, 3][Symbol.iterator](), x => x ** 3); return [it, result]; }); }); diff --git a/packages/algorithm/tests/src/range.spec.ts b/packages/algorithm/tests/src/range.spec.ts index cc1901bfc..06dd576a5 100644 --- a/packages/algorithm/tests/src/range.spec.ts +++ b/packages/algorithm/tests/src/range.spec.ts @@ -7,7 +7,7 @@ | | The full license is in the file LICENSE, distributed with this software. |----------------------------------------------------------------------------*/ -import { range, RangeIterator } from '@lumino/algorithm'; +import { range } from '@lumino/algorithm'; import { testIterator } from './iter.spec'; @@ -43,10 +43,4 @@ describe('@lumino/algorithm', () => { }); }); }); - - describe('RangeIterator', () => { - testIterator(() => { - return [new RangeIterator(0, 11, 2), [0, 2, 4, 6, 8, 10]]; - }); - }); }); diff --git a/packages/algorithm/tests/src/repeat.spec.ts b/packages/algorithm/tests/src/repeat.spec.ts index ccc92e712..7128ffdab 100644 --- a/packages/algorithm/tests/src/repeat.spec.ts +++ b/packages/algorithm/tests/src/repeat.spec.ts @@ -7,7 +7,7 @@ | | The full license is in the file LICENSE, distributed with this software. |----------------------------------------------------------------------------*/ -import { once, repeat, RepeatIterator } from '@lumino/algorithm'; +import { once, repeat } from '@lumino/algorithm'; import { testIterator } from './iter.spec'; @@ -18,15 +18,15 @@ describe('@lumino/algorithm', () => { }); }); - describe('once()', () => { + describe('repeat()', () => { testIterator(() => { - return [once('foo'), ['foo']]; + return [repeat('foo', 3), ['foo', 'foo', 'foo']]; }); }); - describe('RepeatIterator', () => { + describe('once()', () => { testIterator(() => { - return [new RepeatIterator('foo', 3), ['foo', 'foo', 'foo']]; + return [once('foo'), ['foo']]; }); }); }); diff --git a/packages/algorithm/tests/src/retro.spec.ts b/packages/algorithm/tests/src/retro.spec.ts index f3051a26d..205835682 100644 --- a/packages/algorithm/tests/src/retro.spec.ts +++ b/packages/algorithm/tests/src/retro.spec.ts @@ -9,26 +9,26 @@ |----------------------------------------------------------------------------*/ import { expect } from 'chai'; -import { iter, retro, RetroArrayIterator, toArray } from '@lumino/algorithm'; +import { retro } from '@lumino/algorithm'; import { testIterator } from './iter.spec'; describe('@lumino/algorithm', () => { describe('retro()', () => { it('should create an iterator for an array-like object', () => { - expect(toArray(retro([0, 1, 2, 3]))).to.deep.equal([3, 2, 1, 0]); + expect(Array.from(retro([0, 1, 2, 3]))).to.deep.equal([3, 2, 1, 0]); }); it('should call `retro` on a retroable', () => { - let iterator = iter([1, 2, 3, 4]); + let iterator = [1, 2, 3, 4][Symbol.iterator](); let retroable = { retro: () => iterator }; expect(retro(retroable)).to.equal(iterator); }); }); - describe('RetroArrayIterator', () => { + describe('retro()', () => { testIterator(() => { - return [new RetroArrayIterator([1, 2, 3]), [3, 2, 1]]; + return [retro([1, 2, 3]), [3, 2, 1]]; }); }); }); diff --git a/packages/algorithm/tests/src/stride.spec.ts b/packages/algorithm/tests/src/stride.spec.ts index 21e436c8d..fbf0ee586 100644 --- a/packages/algorithm/tests/src/stride.spec.ts +++ b/packages/algorithm/tests/src/stride.spec.ts @@ -7,7 +7,7 @@ | | The full license is in the file LICENSE, distributed with this software. |----------------------------------------------------------------------------*/ -import { iter, stride, StrideIterator } from '@lumino/algorithm'; +import { stride } from '@lumino/algorithm'; import { testIterator } from './iter.spec'; @@ -20,8 +20,8 @@ describe('@lumino/algorithm', () => { describe('StrideIterator', () => { testIterator(() => { - let it = iter([1, 2, 3, 4, 5, 6, 7]); - return [new StrideIterator(it, 3), [1, 4, 7]]; + let it = [1, 2, 3, 4, 5, 6, 7][Symbol.iterator](); + return [stride(it, 3), [1, 4, 7]]; }); }); }); diff --git a/packages/algorithm/tests/src/take.spec.ts b/packages/algorithm/tests/src/take.spec.ts index 9cb54e305..b092a85bf 100644 --- a/packages/algorithm/tests/src/take.spec.ts +++ b/packages/algorithm/tests/src/take.spec.ts @@ -7,7 +7,7 @@ | | The full license is in the file LICENSE, distributed with this software. |----------------------------------------------------------------------------*/ -import { iter, take, TakeIterator } from '@lumino/algorithm'; +import { take } from '@lumino/algorithm'; import { testIterator } from './iter.spec'; @@ -18,9 +18,9 @@ describe('@lumino/algorithm', () => { }); }); - describe('TakeIterator', () => { + describe('take()', () => { testIterator(() => { - return [new TakeIterator(iter([0, 1, 2, 3]), 1), [0]]; + return [take([0, 1, 2, 3][Symbol.iterator](), 1), [0]]; }); }); }); diff --git a/packages/algorithm/tests/src/zip.spec.ts b/packages/algorithm/tests/src/zip.spec.ts index a6a071602..ba75b03a1 100644 --- a/packages/algorithm/tests/src/zip.spec.ts +++ b/packages/algorithm/tests/src/zip.spec.ts @@ -7,7 +7,7 @@ | | The full license is in the file LICENSE, distributed with this software. |----------------------------------------------------------------------------*/ -import { iter, zip, ZipIterator } from '@lumino/algorithm'; +import { zip } from '@lumino/algorithm'; import { testIterator } from './iter.spec'; @@ -25,13 +25,13 @@ describe('@lumino/algorithm', () => { }); }); - describe('ZipIterator', () => { + describe('zip()', () => { testIterator(() => { - let i1 = iter(['one', 'two']); - let i2 = iter([1, 2]); - let i3 = iter([true, false]); + let i1 = ['one', 'two']; + let i2 = [1, 2]; + let i3 = [true, false]; type T = string | number | boolean; - let it = new ZipIterator([i1, i2, i3]); + let it = zip(i1, i2, i3); let results = [ ['one', 1, true], ['two', 2, false] From 518079cf3f1a7768873674ccca4ae8719e2dda09 Mon Sep 17 00:00:00 2001 From: "Afshin T. Darian" Date: Thu, 11 Aug 2022 18:34:44 +0100 Subject: [PATCH 24/62] Update LinkedList to use native iterators --- packages/collections/src/linkedlist.ts | 246 ++++--------------------- 1 file changed, 36 insertions(+), 210 deletions(-) diff --git a/packages/collections/src/linkedlist.ts b/packages/collections/src/linkedlist.ts index a98fe9567..140822cc4 100644 --- a/packages/collections/src/linkedlist.ts +++ b/packages/collections/src/linkedlist.ts @@ -7,18 +7,12 @@ | | The full license is in the file LICENSE, distributed with this software. |----------------------------------------------------------------------------*/ -import { - each, - IIterable, - IIterator, - IRetroable, - IterableOrArrayLike -} from '@lumino/algorithm'; +import { each, IRetroable } from '@lumino/algorithm'; /** * A generic doubly-linked list. */ -export class LinkedList implements IIterable, IRetroable { +export class LinkedList implements Iterable, IRetroable { /** * Whether the list is empty. * @@ -113,8 +107,14 @@ export class LinkedList implements IIterable, IRetroable { * #### Complexity * Constant. */ - iter(): IIterator { - return new LinkedList.ForwardValueIterator(this._first); + [Symbol.iterator](): IterableIterator { + let node = this._first; + return (function* () { + while (node) { + yield node.value; + node = node.next; + } + })(); } /** @@ -125,8 +125,14 @@ export class LinkedList implements IIterable, IRetroable { * #### Complexity * Constant. */ - retro(): IIterator { - return new LinkedList.RetroValueIterator(this._last); + retro(): IterableIterator { + let node = this._last; + return (function* () { + while (node) { + yield node.value; + node = node.prev; + } + })(); } /** @@ -137,8 +143,14 @@ export class LinkedList implements IIterable, IRetroable { * #### Complexity * Constant. */ - nodes(): IIterator> { - return new LinkedList.ForwardNodeIterator(this._first); + nodes(): IterableIterator> { + let node = this._first; + return (function* () { + while (node) { + yield node; + node = node.next; + } + })(); } /** @@ -149,8 +161,14 @@ export class LinkedList implements IIterable, IRetroable { * #### Complexity * Constant. */ - retroNodes(): IIterator> { - return new LinkedList.RetroNodeIterator(this._last); + retroNodes(): IterableIterator> { + let node = this._last; + return (function* () { + while (node) { + yield node; + node = node.prev; + } + })(); } /** @@ -161,7 +179,7 @@ export class LinkedList implements IIterable, IRetroable { * #### Complexity * Linear. */ - assign(values: IterableOrArrayLike): void { + assign(values: Iterable): void { this.clear(); each(values, value => { this.addLast(value); @@ -509,203 +527,11 @@ export namespace LinkedList { * #### Complexity * Linear. */ - export function from(values: IterableOrArrayLike): LinkedList { + export function from(values: Iterable): LinkedList { let list = new LinkedList(); list.assign(values); return list; } - - /** - * A forward iterator for values in a linked list. - */ - export class ForwardValueIterator implements IIterator { - /** - * Construct a forward value iterator. - * - * @param node - The first node in the list. - */ - constructor(node: INode | null) { - this._node = node; - } - - /** - * Get an iterator over the object's values. - * - * @returns An iterator which yields the object's values. - */ - iter(): IIterator { - return this; - } - - /** - * Create an independent clone of the iterator. - * - * @returns A new independent clone of the iterator. - */ - clone(): IIterator { - return new ForwardValueIterator(this._node); - } - - /** - * Get the next value from the iterator. - * - * @returns The next value from the iterator, or `undefined`. - */ - next(): T | undefined { - if (!this._node) { - return undefined; - } - let node = this._node; - this._node = node.next; - return node.value; - } - - private _node: INode | null; - } - - /** - * A reverse iterator for values in a linked list. - */ - export class RetroValueIterator implements IIterator { - /** - * Construct a retro value iterator. - * - * @param node - The last node in the list. - */ - constructor(node: INode | null) { - this._node = node; - } - - /** - * Get an iterator over the object's values. - * - * @returns An iterator which yields the object's values. - */ - iter(): IIterator { - return this; - } - - /** - * Create an independent clone of the iterator. - * - * @returns A new independent clone of the iterator. - */ - clone(): IIterator { - return new RetroValueIterator(this._node); - } - - /** - * Get the next value from the iterator. - * - * @returns The next value from the iterator, or `undefined`. - */ - next(): T | undefined { - if (!this._node) { - return undefined; - } - let node = this._node; - this._node = node.prev; - return node.value; - } - - private _node: INode | null; - } - - /** - * A forward iterator for nodes in a linked list. - */ - export class ForwardNodeIterator implements IIterator> { - /** - * Construct a forward node iterator. - * - * @param node - The first node in the list. - */ - constructor(node: INode | null) { - this._node = node; - } - - /** - * Get an iterator over the object's values. - * - * @returns An iterator which yields the object's values. - */ - iter(): IIterator> { - return this; - } - - /** - * Create an independent clone of the iterator. - * - * @returns A new independent clone of the iterator. - */ - clone(): IIterator> { - return new ForwardNodeIterator(this._node); - } - - /** - * Get the next value from the iterator. - * - * @returns The next value from the iterator, or `undefined`. - */ - next(): INode | undefined { - if (!this._node) { - return undefined; - } - let node = this._node; - this._node = node.next; - return node; - } - - private _node: INode | null; - } - - /** - * A reverse iterator for nodes in a linked list. - */ - export class RetroNodeIterator implements IIterator> { - /** - * Construct a retro node iterator. - * - * @param node - The last node in the list. - */ - constructor(node: INode | null) { - this._node = node; - } - - /** - * Get an iterator over the object's values. - * - * @returns An iterator which yields the object's values. - */ - iter(): IIterator> { - return this; - } - - /** - * Create an independent clone of the iterator. - * - * @returns A new independent clone of the iterator. - */ - clone(): IIterator> { - return new RetroNodeIterator(this._node); - } - - /** - * Get the next value from the iterator. - * - * @returns The next value from the iterator, or `undefined`. - */ - next(): INode | undefined { - if (!this._node) { - return undefined; - } - let node = this._node; - this._node = node.prev; - return node; - } - - private _node: INode | null; - } } /** From 481cfb7c5180a4bc6c75d275737c3cf20ebb45f4 Mon Sep 17 00:00:00 2001 From: "Afshin T. Darian" Date: Thu, 11 Aug 2022 19:33:33 +0100 Subject: [PATCH 25/62] Fix LinkedList tests --- .../collections/tests/src/linkedlist.spec.ts | 154 ++++++------------ 1 file changed, 51 insertions(+), 103 deletions(-) diff --git a/packages/collections/tests/src/linkedlist.spec.ts b/packages/collections/tests/src/linkedlist.spec.ts index 61c47d82e..568d9040d 100644 --- a/packages/collections/tests/src/linkedlist.spec.ts +++ b/packages/collections/tests/src/linkedlist.spec.ts @@ -9,7 +9,7 @@ |----------------------------------------------------------------------------*/ import { expect } from 'chai'; -import { find, map, toArray } from '@lumino/algorithm'; +import { find, map } from '@lumino/algorithm'; import { LinkedList } from '@lumino/collections'; @@ -98,16 +98,17 @@ describe('@lumino/collections', () => { }); }); - describe('#iter()', () => { + describe('@@iterator()', () => { it('should return an iterator over the list values', () => { let data = [0, 1, 2, 3, 4, 5]; let list = LinkedList.from(data); - let it1 = list.iter(); - let it2 = it1.clone(); - expect(it1.iter()).to.equal(it1); - expect(it2.iter()).to.equal(it2); - expect(toArray(it1)).to.deep.equal(data); - expect(toArray(it2)).to.deep.equal(data); + let it1 = list[Symbol.iterator](); + let it2 = list[Symbol.iterator](); + expect(it1[Symbol.iterator]()).to.equal(it1); + expect(it2[Symbol.iterator]()).to.equal(it2); + expect(it1).to.not.equal(it2); + expect(Array.from(it1)).to.deep.equal(data); + expect(Array.from(it2)).to.deep.equal(data); }); }); @@ -117,11 +118,12 @@ describe('@lumino/collections', () => { let reversed = data.slice().reverse(); let list = LinkedList.from(data); let it1 = list.retro(); - let it2 = it1.clone(); - expect(it1.iter()).to.equal(it1); - expect(it2.iter()).to.equal(it2); - expect(toArray(it1)).to.deep.equal(reversed); - expect(toArray(it2)).to.deep.equal(reversed); + let it2 = list.retro(); + expect(it1[Symbol.iterator]()).to.equal(it1); + expect(it2[Symbol.iterator]()).to.equal(it2); + expect(it1).to.not.equal(it2); + expect(Array.from(it1)).to.deep.equal(reversed); + expect(Array.from(it2)).to.deep.equal(reversed); }); }); @@ -130,13 +132,14 @@ describe('@lumino/collections', () => { let data = [0, 1, 2, 3, 4, 5]; let list = LinkedList.from(data); let it1 = list.nodes(); - let it2 = it1.clone(); + let it2 = list.nodes(); let v1 = map(it1, n => n.value); let v2 = map(it2, n => n.value); - expect(it1.iter()).to.equal(it1); - expect(it2.iter()).to.equal(it2); - expect(toArray(v1)).to.deep.equal(data); - expect(toArray(v2)).to.deep.equal(data); + expect(it1[Symbol.iterator]()).to.equal(it1); + expect(it2[Symbol.iterator]()).to.equal(it2); + expect(it1).to.not.equal(it2); + expect(Array.from(v1)).to.deep.equal(data); + expect(Array.from(v2)).to.deep.equal(data); }); }); @@ -146,13 +149,14 @@ describe('@lumino/collections', () => { let reversed = data.slice().reverse(); let list = LinkedList.from(data); let it1 = list.retroNodes(); - let it2 = it1.clone(); + let it2 = list.retroNodes(); let v1 = map(it1, n => n.value); let v2 = map(it2, n => n.value); - expect(it1.iter()).to.equal(it1); - expect(it2.iter()).to.equal(it2); - expect(toArray(v1)).to.deep.equal(reversed); - expect(toArray(v2)).to.deep.equal(reversed); + expect(it1[Symbol.iterator]()).to.equal(it1); + expect(it2[Symbol.iterator]()).to.equal(it2); + expect(it1).to.not.equal(it2); + expect(Array.from(v1)).to.deep.equal(reversed); + expect(Array.from(v2)).to.deep.equal(reversed); }); }); @@ -186,7 +190,7 @@ describe('@lumino/collections', () => { expect(list.first).to.equal(7); expect(list.last).to.equal(99); - expect(toArray(list)).to.deep.equal([7, 42, 99]); + expect(Array.from(list)).to.deep.equal([7, 42, 99]); expect(n1.list).to.equal(list); expect(n1.next).to.equal(null); @@ -235,7 +239,7 @@ describe('@lumino/collections', () => { expect(list.first).to.equal(99); expect(list.last).to.equal(7); - expect(toArray(list)).to.deep.equal([99, 42, 7]); + expect(Array.from(list)).to.deep.equal([99, 42, 7]); expect(n1.list).to.equal(list); expect(n1.next).to.equal(n2); @@ -270,7 +274,7 @@ describe('@lumino/collections', () => { expect(list.length).to.equal(7); expect(list.first).to.equal(9); expect(list.last).to.equal(3); - expect(toArray(list)).to.deep.equal([9, 0, 1, 8, 7, 2, 3]); + expect(Array.from(list)).to.deep.equal([9, 0, 1, 8, 7, 2, 3]); expect(n1.list).to.equal(list); expect(n1.next).to.equal(list.lastNode); @@ -319,7 +323,7 @@ describe('@lumino/collections', () => { expect(list.length).to.equal(7); expect(list.first).to.equal(0); expect(list.last).to.equal(9); - expect(toArray(list)).to.deep.equal([0, 1, 2, 7, 8, 3, 9]); + expect(Array.from(list)).to.deep.equal([0, 1, 2, 7, 8, 3, 9]); expect(n1.list).to.equal(list); expect(n1.next).to.equal(n2); @@ -360,7 +364,7 @@ describe('@lumino/collections', () => { expect(list.length).to.equal(4); expect(list.first).to.equal(0); expect(list.last).to.equal(3); - expect(toArray(list)).to.deep.equal([0, 1, 2, 3]); + expect(Array.from(list)).to.deep.equal([0, 1, 2, 3]); let v1 = list.removeFirst(); @@ -368,7 +372,7 @@ describe('@lumino/collections', () => { expect(list.length).to.equal(3); expect(list.first).to.equal(1); expect(list.last).to.equal(3); - expect(toArray(list)).to.deep.equal([1, 2, 3]); + expect(Array.from(list)).to.deep.equal([1, 2, 3]); let v2 = list.removeFirst(); @@ -376,7 +380,7 @@ describe('@lumino/collections', () => { expect(list.length).to.equal(2); expect(list.first).to.equal(2); expect(list.last).to.equal(3); - expect(toArray(list)).to.deep.equal([2, 3]); + expect(Array.from(list)).to.deep.equal([2, 3]); let v3 = list.removeFirst(); @@ -384,7 +388,7 @@ describe('@lumino/collections', () => { expect(list.length).to.equal(1); expect(list.first).to.equal(3); expect(list.last).to.equal(3); - expect(toArray(list)).to.deep.equal([3]); + expect(Array.from(list)).to.deep.equal([3]); let v4 = list.removeFirst(); @@ -392,7 +396,7 @@ describe('@lumino/collections', () => { expect(list.length).to.equal(0); expect(list.first).to.equal(undefined); expect(list.last).to.equal(undefined); - expect(toArray(list)).to.deep.equal([]); + expect(Array.from(list)).to.deep.equal([]); let v5 = list.removeFirst(); @@ -400,7 +404,7 @@ describe('@lumino/collections', () => { expect(list.length).to.equal(0); expect(list.first).to.equal(undefined); expect(list.last).to.equal(undefined); - expect(toArray(list)).to.deep.equal([]); + expect(Array.from(list)).to.deep.equal([]); expect(v1).to.equal(0); expect(v2).to.equal(1); @@ -418,7 +422,7 @@ describe('@lumino/collections', () => { expect(list.length).to.equal(4); expect(list.first).to.equal(0); expect(list.last).to.equal(3); - expect(toArray(list)).to.deep.equal([0, 1, 2, 3]); + expect(Array.from(list)).to.deep.equal([0, 1, 2, 3]); let v1 = list.removeLast(); @@ -426,7 +430,7 @@ describe('@lumino/collections', () => { expect(list.length).to.equal(3); expect(list.first).to.equal(0); expect(list.last).to.equal(2); - expect(toArray(list)).to.deep.equal([0, 1, 2]); + expect(Array.from(list)).to.deep.equal([0, 1, 2]); let v2 = list.removeLast(); @@ -434,7 +438,7 @@ describe('@lumino/collections', () => { expect(list.length).to.equal(2); expect(list.first).to.equal(0); expect(list.last).to.equal(1); - expect(toArray(list)).to.deep.equal([0, 1]); + expect(Array.from(list)).to.deep.equal([0, 1]); let v3 = list.removeLast(); @@ -442,7 +446,7 @@ describe('@lumino/collections', () => { expect(list.length).to.equal(1); expect(list.first).to.equal(0); expect(list.last).to.equal(0); - expect(toArray(list)).to.deep.equal([0]); + expect(Array.from(list)).to.deep.equal([0]); let v4 = list.removeLast(); @@ -450,7 +454,7 @@ describe('@lumino/collections', () => { expect(list.length).to.equal(0); expect(list.first).to.equal(undefined); expect(list.last).to.equal(undefined); - expect(toArray(list)).to.deep.equal([]); + expect(Array.from(list)).to.deep.equal([]); let v5 = list.removeLast(); @@ -458,7 +462,7 @@ describe('@lumino/collections', () => { expect(list.length).to.equal(0); expect(list.first).to.equal(undefined); expect(list.last).to.equal(undefined); - expect(toArray(list)).to.deep.equal([]); + expect(Array.from(list)).to.deep.equal([]); expect(v1).to.equal(3); expect(v2).to.equal(2); @@ -476,7 +480,7 @@ describe('@lumino/collections', () => { expect(list.length).to.equal(4); expect(list.first).to.equal(0); expect(list.last).to.equal(3); - expect(toArray(list)).to.deep.equal([0, 1, 2, 3]); + expect(Array.from(list)).to.deep.equal([0, 1, 2, 3]); let n1 = find(list.nodes(), n => n.value === 2)!; list.removeNode(n1); @@ -484,7 +488,7 @@ describe('@lumino/collections', () => { expect(list.length).to.equal(3); expect(list.first).to.equal(0); expect(list.last).to.equal(3); - expect(toArray(list)).to.deep.equal([0, 1, 3]); + expect(Array.from(list)).to.deep.equal([0, 1, 3]); expect(n1.list).to.equal(null); expect(n1.next).to.equal(null); expect(n1.prev).to.equal(null); @@ -496,7 +500,7 @@ describe('@lumino/collections', () => { expect(list.length).to.equal(2); expect(list.first).to.equal(0); expect(list.last).to.equal(1); - expect(toArray(list)).to.deep.equal([0, 1]); + expect(Array.from(list)).to.deep.equal([0, 1]); expect(n2.list).to.equal(null); expect(n2.next).to.equal(null); expect(n2.prev).to.equal(null); @@ -508,7 +512,7 @@ describe('@lumino/collections', () => { expect(list.length).to.equal(1); expect(list.first).to.equal(1); expect(list.last).to.equal(1); - expect(toArray(list)).to.deep.equal([1]); + expect(Array.from(list)).to.deep.equal([1]); expect(n3.list).to.equal(null); expect(n3.next).to.equal(null); expect(n3.prev).to.equal(null); @@ -520,7 +524,7 @@ describe('@lumino/collections', () => { expect(list.length).to.equal(0); expect(list.first).to.equal(undefined); expect(list.last).to.equal(undefined); - expect(toArray(list)).to.deep.equal([]); + expect(Array.from(list)).to.deep.equal([]); expect(n4.list).to.equal(null); expect(n4.next).to.equal(null); expect(n4.prev).to.equal(null); @@ -536,7 +540,7 @@ describe('@lumino/collections', () => { expect(list.length).to.equal(4); expect(list.first).to.equal(0); expect(list.last).to.equal(3); - expect(toArray(list)).to.deep.equal([0, 1, 2, 3]); + expect(Array.from(list)).to.deep.equal([0, 1, 2, 3]); list.clear(); @@ -544,7 +548,7 @@ describe('@lumino/collections', () => { expect(list.length).to.equal(0); expect(list.first).to.equal(undefined); expect(list.last).to.equal(undefined); - expect(toArray(list)).to.deep.equal([]); + expect(Array.from(list)).to.deep.equal([]); }); }); @@ -556,63 +560,7 @@ describe('@lumino/collections', () => { expect(list2.length).to.equal(4); expect(list2.first).to.equal(0); expect(list2.last).to.equal(3); - expect(toArray(list2)).to.deep.equal([0, 1, 2, 3]); - }); - }); - - describe('.ForwardValueIterator', () => { - it('should create a forward iterator over the values', () => { - let list = LinkedList.from([0, 1, 2, 3, 4]); - let n = find(list.nodes(), n => n.value === 2)!; - let it1 = new LinkedList.ForwardValueIterator(n); - let it2 = it1.clone(); - expect(it1.iter()).to.equal(it1); - expect(it2.iter()).to.equal(it2); - expect(toArray(it1)).to.deep.equal([2, 3, 4]); - expect(toArray(it2)).to.deep.equal([2, 3, 4]); - }); - }); - - describe('.RetroValueIterator', () => { - it('should create a reverse iterator over the values', () => { - let list = LinkedList.from([0, 1, 2, 3, 4]); - let n = find(list.nodes(), n => n.value === 2)!; - let it1 = new LinkedList.RetroValueIterator(n); - let it2 = it1.clone(); - expect(it1.iter()).to.equal(it1); - expect(it2.iter()).to.equal(it2); - expect(toArray(it1)).to.deep.equal([2, 1, 0]); - expect(toArray(it2)).to.deep.equal([2, 1, 0]); - }); - }); - - describe('.ForwardNodeIterator', () => { - it('should create a forward iterator over the nodes', () => { - let list = LinkedList.from([0, 1, 2, 3, 4]); - let n = find(list.nodes(), n => n.value === 2)!; - let it1 = new LinkedList.ForwardNodeIterator(n); - let it2 = it1.clone(); - let v1 = map(it1, n => n.value); - let v2 = map(it2, n => n.value); - expect(it1.iter()).to.equal(it1); - expect(it2.iter()).to.equal(it2); - expect(toArray(v1)).to.deep.equal([2, 3, 4]); - expect(toArray(v2)).to.deep.equal([2, 3, 4]); - }); - }); - - describe('.RetroNodeIterator', () => { - it('should create a reverse iterator over the nodes', () => { - let list = LinkedList.from([0, 1, 2, 3, 4]); - let n = find(list.nodes(), n => n.value === 2)!; - let it1 = new LinkedList.RetroNodeIterator(n); - let it2 = it1.clone(); - let v1 = map(it1, n => n.value); - let v2 = map(it2, n => n.value); - expect(it1.iter()).to.equal(it1); - expect(it2.iter()).to.equal(it2); - expect(toArray(v1)).to.deep.equal([2, 1, 0]); - expect(toArray(v2)).to.deep.equal([2, 1, 0]); + expect(Array.from(list2)).to.deep.equal([0, 1, 2, 3]); }); }); }); From 82d9b28e41f57e54205678efbbf55cb2697fed8a Mon Sep 17 00:00:00 2001 From: "Afshin T. Darian" Date: Thu, 11 Aug 2022 19:52:32 +0100 Subject: [PATCH 26/62] Update disposable --- packages/disposable/src/index.ts | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/packages/disposable/src/index.ts b/packages/disposable/src/index.ts index ab6a7be05..d61c3000f 100644 --- a/packages/disposable/src/index.ts +++ b/packages/disposable/src/index.ts @@ -7,7 +7,7 @@ | | The full license is in the file LICENSE, distributed with this software. |----------------------------------------------------------------------------*/ -import { each, IterableOrArrayLike } from '@lumino/algorithm'; +import { each } from '@lumino/algorithm'; import { ISignal, Signal } from '@lumino/signaling'; @@ -196,7 +196,7 @@ export namespace DisposableSet { * * @returns A new disposable initialized with the given items. */ - export function from(items: IterableOrArrayLike): DisposableSet { + export function from(items: Iterable): DisposableSet { let set = new DisposableSet(); each(items, item => { set.add(item); @@ -248,9 +248,7 @@ export namespace ObservableDisposableSet { * * @returns A new disposable initialized with the given items. */ - export function from( - items: IterableOrArrayLike - ): ObservableDisposableSet { + export function from(items: Iterable): ObservableDisposableSet { let set = new ObservableDisposableSet(); each(items, item => { set.add(item); From b4c1250647e73648d7e0fef6332669da5e519afd Mon Sep 17 00:00:00 2001 From: "Afshin T. Darian" Date: Thu, 11 Aug 2022 20:40:40 +0100 Subject: [PATCH 27/62] Update widgets to use native iterators --- packages/widgets/src/docklayout.ts | 44 ++++++++++++------------- packages/widgets/src/dockpanel.ts | 14 ++++---- packages/widgets/src/gridlayout.ts | 4 +-- packages/widgets/src/layout.ts | 6 ++-- packages/widgets/src/panellayout.ts | 6 ++-- packages/widgets/src/singletonlayout.ts | 4 +-- packages/widgets/src/widget.ts | 6 ++-- packages/widgets/tsconfig.json | 2 +- 8 files changed, 42 insertions(+), 44 deletions(-) diff --git a/packages/widgets/src/docklayout.ts b/packages/widgets/src/docklayout.ts index b9bf62f63..6995153af 100644 --- a/packages/widgets/src/docklayout.ts +++ b/packages/widgets/src/docklayout.ts @@ -10,10 +10,8 @@ import { ArrayExt, chain, - ChainIterator, each, empty, - IIterator, map, once, reduce @@ -68,7 +66,7 @@ export class DockLayout extends Layout { */ dispose(): void { // Get an iterator over the widgets in the layout. - let widgets = this.iter(); + let widgets = this[Symbol.iterator](); // Dispose of the layout items. this._items.forEach(item => { @@ -155,7 +153,7 @@ export class DockLayout extends Layout { * #### Notes * This iterator includes the generated tab bars. */ - iter(): IIterator { + [Symbol.iterator](): IterableIterator { return this._root ? this._root.iterAllWidgets() : empty(); } @@ -167,7 +165,7 @@ export class DockLayout extends Layout { * #### Notes * This iterator does not include the generated tab bars. */ - widgets(): IIterator { + widgets(): IterableIterator { return this._root ? this._root.iterUserWidgets() : empty(); } @@ -180,7 +178,7 @@ export class DockLayout extends Layout { * This iterator yields the widgets corresponding to the current tab * of each tab bar in the layout. */ - selectedWidgets(): IIterator { + selectedWidgets(): IterableIterator { return this._root ? this._root.iterSelectedWidgets() : empty(); } @@ -192,7 +190,7 @@ export class DockLayout extends Layout { * #### Notes * This iterator does not include the user widgets. */ - tabBars(): IIterator> { + tabBars(): IterableIterator> { return this._root ? this._root.iterTabBars() : empty>(); } @@ -201,7 +199,7 @@ export class DockLayout extends Layout { * * @returns A new iterator over the handles in the layout. */ - handles(): IIterator { + handles(): IterableIterator { return this._root ? this._root.iterHandles() : empty(); } @@ -1561,21 +1559,21 @@ namespace Private { /** * Create an iterator for all widgets in the layout tree. */ - iterAllWidgets(): IIterator { + iterAllWidgets(): IterableIterator { return chain(once(this.tabBar), this.iterUserWidgets()); } /** * Create an iterator for the user widgets in the layout tree. */ - iterUserWidgets(): IIterator { + iterUserWidgets(): IterableIterator { return map(this.tabBar.titles, title => title.owner); } /** * Create an iterator for the selected widgets in the layout tree. */ - iterSelectedWidgets(): IIterator { + iterSelectedWidgets(): IterableIterator { let title = this.tabBar.currentTitle; return title ? once(title.owner) : empty(); } @@ -1583,14 +1581,14 @@ namespace Private { /** * Create an iterator for the tab bars in the layout tree. */ - iterTabBars(): IIterator> { + iterTabBars(): IterableIterator> { return once(this.tabBar); } /** * Create an iterator for the handles in the layout tree. */ - iterHandles(): IIterator { + iterHandles(): IterableIterator { return empty(); } @@ -1797,41 +1795,41 @@ namespace Private { /** * Create an iterator for all widgets in the layout tree. */ - iterAllWidgets(): IIterator { + iterAllWidgets(): IterableIterator { let children = map(this.children, child => child.iterAllWidgets()); - return new ChainIterator(children); + return chain(...children); } /** * Create an iterator for the user widgets in the layout tree. */ - iterUserWidgets(): IIterator { + iterUserWidgets(): IterableIterator { let children = map(this.children, child => child.iterUserWidgets()); - return new ChainIterator(children); + return chain(...children); } /** * Create an iterator for the selected widgets in the layout tree. */ - iterSelectedWidgets(): IIterator { + iterSelectedWidgets(): IterableIterator { let children = map(this.children, child => child.iterSelectedWidgets()); - return new ChainIterator(children); + return chain(...children); } /** * Create an iterator for the tab bars in the layout tree. */ - iterTabBars(): IIterator> { + iterTabBars(): IterableIterator> { let children = map(this.children, child => child.iterTabBars()); - return new ChainIterator>(children); + return chain>(...children); } /** * Create an iterator for the handles in the layout tree. */ - iterHandles(): IIterator { + iterHandles(): IterableIterator { let children = map(this.children, child => child.iterHandles()); - return chain(this.handles, new ChainIterator(children)); + return chain(this.handles, ...children); } /** diff --git a/packages/widgets/src/dockpanel.ts b/packages/widgets/src/dockpanel.ts index 743bd15b3..761ad749d 100644 --- a/packages/widgets/src/dockpanel.ts +++ b/packages/widgets/src/dockpanel.ts @@ -7,7 +7,7 @@ | | The full license is in the file LICENSE, distributed with this software. |----------------------------------------------------------------------------*/ -import { each, find, IIterator, toArray } from '@lumino/algorithm'; +import { each, find } from '@lumino/algorithm'; import { MimeData } from '@lumino/coreutils'; @@ -270,7 +270,7 @@ export class DockPanel extends Widget { * #### Notes * This iterator does not include the generated tab bars. */ - widgets(): IIterator { + widgets(): IterableIterator { return (this.layout as DockLayout).widgets(); } @@ -283,7 +283,7 @@ export class DockPanel extends Widget { * This iterator yields the widgets corresponding to the current tab * of each tab bar in the panel. */ - selectedWidgets(): IIterator { + selectedWidgets(): IterableIterator { return (this.layout as DockLayout).selectedWidgets(); } @@ -295,7 +295,7 @@ export class DockPanel extends Widget { * #### Notes * This iterator does not include the user widgets. */ - tabBars(): IIterator> { + tabBars(): IterableIterator> { return (this.layout as DockLayout).tabBars(); } @@ -304,7 +304,7 @@ export class DockPanel extends Widget { * * @returns A new iterator over the handles in the panel. */ - handles(): IIterator { + handles(): IterableIterator { return (this.layout as DockLayout).handles(); } @@ -1553,10 +1553,10 @@ namespace Private { } // Get a flat array of the widgets in the panel. - let widgets = toArray(panel.widgets()); + let widgets = Array.from(panel.widgets()); // Get the first selected widget in the panel. - let selected = panel.selectedWidgets().next(); + let selected = panel.selectedWidgets().next().value; // Compute the current index for the new config. let currentIndex = selected ? widgets.indexOf(selected) : -1; diff --git a/packages/widgets/src/gridlayout.ts b/packages/widgets/src/gridlayout.ts index a77f05121..ac03f0cb8 100644 --- a/packages/widgets/src/gridlayout.ts +++ b/packages/widgets/src/gridlayout.ts @@ -7,7 +7,7 @@ | | The full license is in the file LICENSE, distributed with this software. |----------------------------------------------------------------------------*/ -import { ArrayExt, each, IIterator, map } from '@lumino/algorithm'; +import { ArrayExt, each, map } from '@lumino/algorithm'; import { ElementExt } from '@lumino/domutils'; @@ -288,7 +288,7 @@ export class GridLayout extends Layout { * * @returns A new iterator over the widgets in the layout. */ - iter(): IIterator { + [Symbol.iterator](): IterableIterator { return map(this._items, item => item.widget); } diff --git a/packages/widgets/src/layout.ts b/packages/widgets/src/layout.ts index d4337f9c0..2ec0913cb 100644 --- a/packages/widgets/src/layout.ts +++ b/packages/widgets/src/layout.ts @@ -8,7 +8,7 @@ | | The full license is in the file LICENSE, distributed with this software. |----------------------------------------------------------------------------*/ -import { each, IIterable, IIterator } from '@lumino/algorithm'; +import { each } from '@lumino/algorithm'; import { IDisposable } from '@lumino/disposable'; @@ -36,7 +36,7 @@ import { Widget } from './widget'; * widgets to the layout. A subclass should define that API in a way * which is meaningful for its intended use. */ -export abstract class Layout implements IIterable, IDisposable { +export abstract class Layout implements Iterable, IDisposable { /** * Construct a new layout. * @@ -151,7 +151,7 @@ export abstract class Layout implements IIterable, IDisposable { * #### Notes * This abstract method must be implemented by a subclass. */ - abstract iter(): IIterator; + abstract [Symbol.iterator](): IterableIterator; /** * Remove a widget from the layout. diff --git a/packages/widgets/src/panellayout.ts b/packages/widgets/src/panellayout.ts index 98197e5c7..cce7751af 100644 --- a/packages/widgets/src/panellayout.ts +++ b/packages/widgets/src/panellayout.ts @@ -7,7 +7,7 @@ | | The full license is in the file LICENSE, distributed with this software. |----------------------------------------------------------------------------*/ -import { ArrayExt, each, IIterator, iter } from '@lumino/algorithm'; +import { ArrayExt, each } from '@lumino/algorithm'; import { MessageLoop } from '@lumino/messaging'; @@ -53,8 +53,8 @@ export class PanelLayout extends Layout { * * @returns A new iterator over the widgets in the layout. */ - iter(): IIterator { - return iter(this._widgets); + [Symbol.iterator](): IterableIterator { + return this._widgets[Symbol.iterator](); } /** diff --git a/packages/widgets/src/singletonlayout.ts b/packages/widgets/src/singletonlayout.ts index 400364516..9cc06c0fc 100644 --- a/packages/widgets/src/singletonlayout.ts +++ b/packages/widgets/src/singletonlayout.ts @@ -7,7 +7,7 @@ | | The full license is in the file LICENSE, distributed with this software. |----------------------------------------------------------------------------*/ -import { each, empty, IIterator, once } from '@lumino/algorithm'; +import { each, empty, once } from '@lumino/algorithm'; import { MessageLoop } from '@lumino/messaging'; @@ -81,7 +81,7 @@ export class SingletonLayout extends Layout { * * @returns A new iterator over the widgets in the layout. */ - iter(): IIterator { + [Symbol.iterator](): IterableIterator { return this._widget ? once(this._widget) : empty(); } diff --git a/packages/widgets/src/widget.ts b/packages/widgets/src/widget.ts index 9f5ef8259..09a84cf55 100644 --- a/packages/widgets/src/widget.ts +++ b/packages/widgets/src/widget.ts @@ -8,7 +8,7 @@ | | The full license is in the file LICENSE, distributed with this software. |----------------------------------------------------------------------------*/ -import { empty, IIterator } from '@lumino/algorithm'; +import { empty } from '@lumino/algorithm'; import { IObservableDisposable } from '@lumino/disposable'; @@ -283,8 +283,8 @@ export class Widget implements IMessageHandler, IObservableDisposable { * * If a layout is not installed, the returned iterator will be empty. */ - children(): IIterator { - return this._layout ? this._layout.iter() : empty(); + children(): IterableIterator { + return this._layout ? this._layout[Symbol.iterator]() : empty(); } /** diff --git a/packages/widgets/tsconfig.json b/packages/widgets/tsconfig.json index ea4f91321..5e66d6012 100644 --- a/packages/widgets/tsconfig.json +++ b/packages/widgets/tsconfig.json @@ -2,7 +2,7 @@ "extends": "../../tsconfigbase", "compilerOptions": { "declarationDir": "types", - "lib": ["DOM", "ES6"], + "lib": ["DOM", "DOM.Iterable", "ES6"], "outDir": "lib", "rootDir": "src" }, From 3ab8cb1ba5e77bf314c0df370ac2d30a805a7458 Mon Sep 17 00:00:00 2001 From: "Afshin T. Darian" Date: Thu, 11 Aug 2022 20:45:33 +0100 Subject: [PATCH 28/62] Fix widget tests --- packages/widgets/tests/src/layout.spec.ts | 8 ++++---- packages/widgets/tests/src/panellayout.spec.ts | 4 ++-- packages/widgets/tests/src/widget.spec.ts | 8 ++++---- 3 files changed, 10 insertions(+), 10 deletions(-) diff --git a/packages/widgets/tests/src/layout.spec.ts b/packages/widgets/tests/src/layout.spec.ts index 5da8173e6..7aeeae16b 100644 --- a/packages/widgets/tests/src/layout.spec.ts +++ b/packages/widgets/tests/src/layout.spec.ts @@ -9,7 +9,7 @@ |----------------------------------------------------------------------------*/ import { expect } from 'chai'; -import { ArrayExt, every, IIterator, iter, toArray } from '@lumino/algorithm'; +import { ArrayExt, every } from '@lumino/algorithm'; import { Message, MessageLoop } from '@lumino/messaging'; @@ -29,8 +29,8 @@ class LogLayout extends Layout { super.dispose(); } - iter(): IIterator { - return iter(this.widgets); + [Symbol.iterator](): IterableIterator { + return this.widgets[Symbol.iterator](); } removeWidget(widget: Widget): void { @@ -113,7 +113,7 @@ describe('@lumino/widgets', () => { let widget = new Widget(); let layout = new LogLayout(); widget.layout = layout; - let children = toArray(widget.children()); + let children = Array.from(widget.children()); layout.dispose(); expect(layout.parent).to.equal(null); expect(every(children, w => w.isDisposed)).to.equal(true); diff --git a/packages/widgets/tests/src/panellayout.spec.ts b/packages/widgets/tests/src/panellayout.spec.ts index cae746164..23bda9a0f 100644 --- a/packages/widgets/tests/src/panellayout.spec.ts +++ b/packages/widgets/tests/src/panellayout.spec.ts @@ -97,9 +97,9 @@ describe('@lumino/widgets', () => { each(widgets, w => { w.title.label = 'foo'; }); - let iter = layout.iter(); + let iter = layout[Symbol.iterator](); expect(every(iter, w => w.title.label === 'foo')).to.equal(true); - expect(layout.iter()).to.not.equal(iter); + expect(layout[Symbol.iterator]()).to.not.equal(iter); }); }); diff --git a/packages/widgets/tests/src/widget.spec.ts b/packages/widgets/tests/src/widget.spec.ts index 82e6c750f..e2fe4cd8c 100644 --- a/packages/widgets/tests/src/widget.spec.ts +++ b/packages/widgets/tests/src/widget.spec.ts @@ -9,7 +9,7 @@ |----------------------------------------------------------------------------*/ import { expect } from 'chai'; -import { ArrayExt, each, IIterator, iter } from '@lumino/algorithm'; +import { ArrayExt, each } from '@lumino/algorithm'; import { Message, MessageLoop } from '@lumino/messaging'; @@ -93,8 +93,8 @@ class TestLayout extends Layout { super.dispose(); } - iter(): IIterator { - return iter(this._widgets); + [Symbol.iterator](): IterableIterator { + return this._widgets[Symbol.iterator](); } removeWidget(widget: Widget): void { @@ -401,7 +401,7 @@ describe('@lumino/widgets', () => { it('should return an empty iterator if there is no layout', () => { let widget = new Widget(); - expect(widget.children().next()).to.equal(undefined); + expect(widget.children().next().done).to.equal(true); }); }); From 3d633c41cedbc3a495c6940807296a4a15808aa3 Mon Sep 17 00:00:00 2001 From: "Afshin T. Darian" Date: Thu, 11 Aug 2022 21:15:11 +0100 Subject: [PATCH 29/62] Update data grid to use native iterators --- packages/datagrid/src/basickeyhandler.ts | 4 +++- packages/datagrid/src/basicselectionmodel.ts | 6 ++---- packages/datagrid/src/datagrid.ts | 8 ++++---- packages/datagrid/src/selectionmodel.ts | 4 ++-- 4 files changed, 11 insertions(+), 11 deletions(-) diff --git a/packages/datagrid/src/basickeyhandler.ts b/packages/datagrid/src/basickeyhandler.ts index 64d7a5190..e47befb55 100644 --- a/packages/datagrid/src/basickeyhandler.ts +++ b/packages/datagrid/src/basickeyhandler.ts @@ -759,9 +759,11 @@ export class BasicKeyHandler implements DataGrid.IKeyHandler { let maxColumn = dataModel.columnCount('body') - 1; const it = grid.selectionModel!.selections(); + let r: IteratorResult; let s: SelectionModel.Selection | undefined; - while ((s = it.next()) !== undefined) { + while (!(r = it.next()).done) { // Clamp the cell to the model bounds. + s = r.value; let sr1 = Math.max(0, Math.min(s.r1, maxRow)); let sc1 = Math.max(0, Math.min(s.c1, maxColumn)); let sr2 = Math.max(0, Math.min(s.r2, maxRow)); diff --git a/packages/datagrid/src/basicselectionmodel.ts b/packages/datagrid/src/basicselectionmodel.ts index ffd04d296..75791babb 100644 --- a/packages/datagrid/src/basicselectionmodel.ts +++ b/packages/datagrid/src/basicselectionmodel.ts @@ -7,8 +7,6 @@ | | The full license is in the file LICENSE, distributed with this software. |----------------------------------------------------------------------------*/ -import { IIterator, iter } from '@lumino/algorithm'; - import { DataModel } from './datamodel'; import { SelectionModel } from './selectionmodel'; @@ -152,8 +150,8 @@ export class BasicSelectionModel extends SelectionModel { * #### Notes * The data grid will render the selections in order. */ - selections(): IIterator { - return iter(this._selections); + selections(): IterableIterator { + return this._selections[Symbol.iterator](); } /** diff --git a/packages/datagrid/src/datagrid.ts b/packages/datagrid/src/datagrid.ts index 7dda9b21f..e685ba2e5 100644 --- a/packages/datagrid/src/datagrid.ts +++ b/packages/datagrid/src/datagrid.ts @@ -7,8 +7,6 @@ | | The full license is in the file LICENSE, distributed with this software. |----------------------------------------------------------------------------*/ -import { toArray } from '@lumino/algorithm'; - import { IDisposable } from '@lumino/disposable'; import { ClipboardExt, ElementExt, Platform } from '@lumino/domutils'; @@ -1767,7 +1765,7 @@ export class DataGrid extends Widget { } // Coerce the selections to an array. - let selections = toArray(selectionModel.selections()); + let selections = Array.from(selectionModel.selections()); // Bail early if there are no selections. if (selections.length === 0) { @@ -5195,9 +5193,11 @@ export class DataGrid extends Widget { // Iterate over the selections. let it = model.selections(); + let r: IteratorResult; let s: SelectionModel.Selection | undefined; - while ((s = it.next()) !== undefined) { + while (!(r = it.next()).done) { // Skip the section if it's not visible. + s = r.value; if (s.r1 < r1 && s.r2 < r1) { continue; } diff --git a/packages/datagrid/src/selectionmodel.ts b/packages/datagrid/src/selectionmodel.ts index 912275b80..721780d4e 100644 --- a/packages/datagrid/src/selectionmodel.ts +++ b/packages/datagrid/src/selectionmodel.ts @@ -7,7 +7,7 @@ | | The full license is in the file LICENSE, distributed with this software. |----------------------------------------------------------------------------*/ -import { IIterator, some } from '@lumino/algorithm'; +import { some } from '@lumino/algorithm'; import { ISignal, Signal } from '@lumino/signaling'; @@ -82,7 +82,7 @@ export abstract class SelectionModel { * #### Notes * The data grid will render the selections in order. */ - abstract selections(): IIterator; + abstract selections(): IterableIterator; /** * Select the specified cells. From 4f1a5c14d37fb878d23ed961ec5eae0460055319 Mon Sep 17 00:00:00 2001 From: "Afshin T. Darian" Date: Thu, 11 Aug 2022 21:24:24 +0100 Subject: [PATCH 30/62] Update API report --- review/api/algorithm.api.md | 227 ++++------------------------------ review/api/collections.api.md | 41 ++---- review/api/datagrid.api.md | 5 +- review/api/disposable.api.md | 5 +- review/api/widgets.api.md | 32 +++-- 5 files changed, 50 insertions(+), 260 deletions(-) diff --git a/review/api/algorithm.api.md b/review/api/algorithm.api.md index 36c74bc7b..12e184427 100644 --- a/review/api/algorithm.api.md +++ b/review/api/algorithm.api.md @@ -48,214 +48,69 @@ export namespace ArrayExt { } // @public -export class ArrayIterator implements IIterator { - constructor(source: ArrayLike); - clone(): IIterator; - iter(): IIterator; - next(): T | undefined; -} - -// @public -export function chain(...objects: IterableOrArrayLike[]): IIterator; - -// @public -export class ChainIterator implements IIterator { - constructor(source: IIterator>); - clone(): IIterator; - iter(): IIterator; - next(): T | undefined; -} - -// @public -export function each(object: IterableOrArrayLike, fn: (value: T, index: number) => boolean | void): void; - -// @public -export function empty(): IIterator; - -// @public -export class EmptyIterator implements IIterator { - clone(): IIterator; - iter(): IIterator; - next(): T | undefined; -} - -// @public -export function enumerate(object: IterableOrArrayLike, start?: number): IIterator<[number, T]>; - -// @public -export class EnumerateIterator implements IIterator<[number, T]> { - constructor(source: IIterator, start: number); - clone(): IIterator<[number, T]>; - iter(): IIterator<[number, T]>; - next(): [number, T] | undefined; -} +export function chain(...objects: Iterable[]): IterableIterator; // @public -export function every(object: IterableOrArrayLike, fn: (value: T, index: number) => boolean): boolean; +export function each(object: Iterable, fn: (value: T, index: number) => boolean | void): void; // @public -export function filter(object: IterableOrArrayLike, fn: (value: T, index: number) => boolean): IIterator; +export function empty(): IterableIterator; // @public -export class FilterIterator implements IIterator { - constructor(source: IIterator, fn: (value: T, index: number) => boolean); - clone(): IIterator; - iter(): IIterator; - next(): T | undefined; -} +export function enumerate(object: Iterable, start?: number): IterableIterator<[number, T]>; // @public -export function find(object: IterableOrArrayLike, fn: (value: T, index: number) => boolean): T | undefined; +export function every(object: Iterable, fn: (value: T, index: number) => boolean): boolean; // @public -export function findIndex(object: IterableOrArrayLike, fn: (value: T, index: number) => boolean): number; +export function filter(object: Iterable, fn: (value: T, index: number) => boolean): IterableIterator; // @public -export class FnIterator implements IIterator { - constructor(fn: () => T | undefined); - clone(): IIterator; - iter(): IIterator; - next(): T | undefined; -} +export function find(object: Iterable, fn: (value: T, index: number) => boolean): T | undefined; // @public -export interface IIterable { - iter(): IIterator; -} - -// @public -export interface IIterator extends IIterable { - clone(): IIterator; - next(): T | undefined; -} +export function findIndex(object: Iterable, fn: (value: T, index: number) => boolean): number; // @public export interface IRetroable { - retro(): IIterator; -} - -// @public -export class ItemIterator implements IIterator<[string, T]> { - constructor(source: { - readonly [key: string]: T; - }, keys?: string[]); - clone(): IIterator<[string, T]>; - iter(): IIterator<[string, T]>; - next(): [string, T] | undefined; -} - -// @public -export function iter(object: IterableOrArrayLike): IIterator; - -// @public -export type IterableOrArrayLike = IIterable | ArrayLike; - -// @public -export function iterFn(fn: () => T | undefined): IIterator; - -// @public -export function iterItems(object: { - readonly [key: string]: T; -}): IIterator<[string, T]>; - -// @public -export function iterKeys(object: { - readonly [key: string]: T; -}): IIterator; - -// @public -export function iterValues(object: { - readonly [key: string]: T; -}): IIterator; - -// @public -export class KeyIterator implements IIterator { - constructor(source: { - readonly [key: string]: any; - }, keys?: string[]); - clone(): IIterator; - iter(): IIterator; - next(): string | undefined; -} - -// @public -export function map(object: IterableOrArrayLike, fn: (value: T, index: number) => U): IIterator; - -// @public -export class MapIterator implements IIterator { - constructor(source: IIterator, fn: (value: T, index: number) => U); - clone(): IIterator; - iter(): IIterator; - next(): U | undefined; + retro(): IterableIterator; } // @public -export function max(object: IterableOrArrayLike, fn: (first: T, second: T) => number): T | undefined; +export function map(object: Iterable, fn: (value: T, index: number) => U): IterableIterator; // @public -export function min(object: IterableOrArrayLike, fn: (first: T, second: T) => number): T | undefined; +export function max(object: Iterable, fn: (first: T, second: T) => number): T | undefined; // @public -export function minmax(object: IterableOrArrayLike, fn: (first: T, second: T) => number): [T, T] | undefined; +export function min(object: Iterable, fn: (first: T, second: T) => number): T | undefined; // @public -export function once(value: T): IIterator; +export function minmax(object: Iterable, fn: (first: T, second: T) => number): [T, T] | undefined; // @public -export function range(start: number, stop?: number, step?: number): IIterator; +export function once(value: T): IterableIterator; // @public -export class RangeIterator implements IIterator { - constructor(start: number, stop: number, step: number); - clone(): IIterator; - iter(): IIterator; - next(): number | undefined; -} +export function range(start: number, stop?: number, step?: number): IterableIterator; // @public -export function reduce(object: IterableOrArrayLike, fn: (accumulator: T, value: T, index: number) => T): T; +export function reduce(object: Iterable, fn: (accumulator: T, value: T, index: number) => T): T; // @public (undocumented) -export function reduce(object: IterableOrArrayLike, fn: (accumulator: U, value: T, index: number) => U, initial: U): U; - -// @public -export function repeat(value: T, count: number): IIterator; - -// @public -export class RepeatIterator implements IIterator { - constructor(value: T, count: number); - clone(): IIterator; - iter(): IIterator; - next(): T | undefined; -} - -// @public -export function retro(object: RetroableOrArrayLike): IIterator; +export function reduce(object: Iterable, fn: (accumulator: U, value: T, index: number) => U, initial: U): U; // @public -export type RetroableOrArrayLike = IRetroable | ArrayLike; +export function repeat(value: T, count: number): IterableIterator; // @public -export class RetroArrayIterator implements IIterator { - constructor(source: ArrayLike); - clone(): IIterator; - iter(): IIterator; - next(): T | undefined; -} +export function retro(object: IRetroable | ArrayLike): IterableIterator; // @public -export function some(object: IterableOrArrayLike, fn: (value: T, index: number) => boolean): boolean; +export function some(object: Iterable, fn: (value: T, index: number) => boolean): boolean; // @public -export function stride(object: IterableOrArrayLike, step: number): IIterator; - -// @public -export class StrideIterator implements IIterator { - constructor(source: IIterator, step: number); - clone(): IIterator; - iter(): IIterator; - next(): T | undefined; -} +export function stride(object: Iterable, step: number): IterableIterator; // @public export namespace StringExt { @@ -271,47 +126,13 @@ export namespace StringExt { } // @public -export function take(object: IterableOrArrayLike, count: number): IIterator; - -// @public -export class TakeIterator implements IIterator { - constructor(source: IIterator, count: number); - clone(): IIterator; - iter(): IIterator; - next(): T | undefined; -} - -// @public -export function toArray(object: IterableOrArrayLike): T[]; - -// @public -export function toObject(object: IterableOrArrayLike<[string, T]>): { - [key: string]: T; -}; +export function take(object: Iterable, count: number): IterableIterator; // @public -export function topologicSort(edges: IterableOrArrayLike<[T, T]>): T[]; +export function topologicSort(edges: Iterable<[T, T]>): T[]; // @public -export class ValueIterator implements IIterator { - constructor(source: { - readonly [key: string]: T; - }, keys?: string[]); - clone(): IIterator; - iter(): IIterator; - next(): T | undefined; -} - -// @public -export function zip(...objects: IterableOrArrayLike[]): IIterator; - -// @public -export class ZipIterator implements IIterator { - constructor(source: IIterator[]); - clone(): IIterator; - iter(): IIterator; - next(): T[] | undefined; -} +export function zip(...objects: Iterable[]): IterableIterator; // (No @packageDocumentation comment for this package) diff --git a/review/api/collections.api.md b/review/api/collections.api.md index e6c4e5565..e96b4f08e 100644 --- a/review/api/collections.api.md +++ b/review/api/collections.api.md @@ -4,34 +4,31 @@ ```ts -import { IIterable } from '@lumino/algorithm'; -import { IIterator } from '@lumino/algorithm'; import { IRetroable } from '@lumino/algorithm'; -import { IterableOrArrayLike } from '@lumino/algorithm'; // @public -export class LinkedList implements IIterable, IRetroable { +export class LinkedList implements Iterable, IRetroable { + [Symbol.iterator](): IterableIterator; addFirst(value: T): LinkedList.INode; addLast(value: T): LinkedList.INode; - assign(values: IterableOrArrayLike): void; + assign(values: Iterable): void; clear(): void; get first(): T | undefined; get firstNode(): LinkedList.INode | null; insertAfter(value: T, ref: LinkedList.INode | null): LinkedList.INode; insertBefore(value: T, ref: LinkedList.INode | null): LinkedList.INode; get isEmpty(): boolean; - iter(): IIterator; get last(): T | undefined; get lastNode(): LinkedList.INode | null; get length(): number; - nodes(): IIterator>; + nodes(): IterableIterator>; pop(): T | undefined; push(value: T): void; removeFirst(): T | undefined; removeLast(): T | undefined; removeNode(node: LinkedList.INode): void; - retro(): IIterator; - retroNodes(): IIterator>; + retro(): IterableIterator; + retroNodes(): IterableIterator>; shift(value: T): void; get size(): number; unshift(): T | undefined; @@ -39,37 +36,13 @@ export class LinkedList implements IIterable, IRetroable { // @public export namespace LinkedList { - export class ForwardNodeIterator implements IIterator> { - constructor(node: INode | null); - clone(): IIterator>; - iter(): IIterator>; - next(): INode | undefined; - } - export class ForwardValueIterator implements IIterator { - constructor(node: INode | null); - clone(): IIterator; - iter(): IIterator; - next(): T | undefined; - } - export function from(values: IterableOrArrayLike): LinkedList; + export function from(values: Iterable): LinkedList; export interface INode { readonly list: LinkedList | null; readonly next: INode | null; readonly prev: INode | null; readonly value: T; } - export class RetroNodeIterator implements IIterator> { - constructor(node: INode | null); - clone(): IIterator>; - iter(): IIterator>; - next(): INode | undefined; - } - export class RetroValueIterator implements IIterator { - constructor(node: INode | null); - clone(): IIterator; - iter(): IIterator; - next(): T | undefined; - } } // (No @packageDocumentation comment for this package) diff --git a/review/api/datagrid.api.md b/review/api/datagrid.api.md index 8e02f9f68..9197a5041 100644 --- a/review/api/datagrid.api.md +++ b/review/api/datagrid.api.md @@ -5,7 +5,6 @@ ```ts import { IDisposable } from '@lumino/disposable'; -import { IIterator } from '@lumino/algorithm'; import { IMessageHandler } from '@lumino/messaging'; import { ISignal } from '@lumino/signaling'; import { Message } from '@lumino/messaging'; @@ -58,7 +57,7 @@ export class BasicSelectionModel extends SelectionModel { moveCursorWithinSelections(direction: SelectionModel.CursorMoveDirection): void; protected onDataModelChanged(sender: DataModel, args: DataModel.ChangedArgs): void; select(args: SelectionModel.SelectArgs): void; - selections(): IIterator; + selections(): IterableIterator; } // @public @@ -851,7 +850,7 @@ export abstract class SelectionModel { abstract select(args: SelectionModel.SelectArgs): void; get selectionMode(): SelectionModel.SelectionMode; set selectionMode(value: SelectionModel.SelectionMode); - abstract selections(): IIterator; + abstract selections(): IterableIterator; } // @public diff --git a/review/api/disposable.api.md b/review/api/disposable.api.md index 5a3163362..dca0605b5 100644 --- a/review/api/disposable.api.md +++ b/review/api/disposable.api.md @@ -5,7 +5,6 @@ ```ts import { ISignal } from '@lumino/signaling'; -import { IterableOrArrayLike } from '@lumino/algorithm'; // @public export class DisposableDelegate implements IDisposable { @@ -26,7 +25,7 @@ export class DisposableSet implements IDisposable { // @public export namespace DisposableSet { - export function from(items: IterableOrArrayLike): DisposableSet; + export function from(items: Iterable): DisposableSet; } // @public @@ -54,7 +53,7 @@ export class ObservableDisposableSet extends DisposableSet implements IObservabl // @public export namespace ObservableDisposableSet { - export function from(items: IterableOrArrayLike): ObservableDisposableSet; + export function from(items: Iterable): ObservableDisposableSet; } // (No @packageDocumentation comment for this package) diff --git a/review/api/widgets.api.md b/review/api/widgets.api.md index df1bc06e5..c0c6a11a8 100644 --- a/review/api/widgets.api.md +++ b/review/api/widgets.api.md @@ -11,8 +11,6 @@ import { ElementDataset } from '@lumino/virtualdom'; import { ElementInlineStyle } from '@lumino/virtualdom'; import { h } from '@lumino/virtualdom'; import { IDisposable } from '@lumino/disposable'; -import { IIterable } from '@lumino/algorithm'; -import { IIterator } from '@lumino/algorithm'; import { IMessageHandler } from '@lumino/messaging'; import { IObservableDisposable } from '@lumino/disposable'; import { ISignal } from '@lumino/signaling'; @@ -281,18 +279,18 @@ export namespace ContextMenu { // @public export class DockLayout extends Layout { + [Symbol.iterator](): IterableIterator; constructor(options: DockLayout.IOptions); addWidget(widget: Widget, options?: DockLayout.IAddOptions): void; protected attachWidget(widget: Widget): void; protected detachWidget(widget: Widget): void; dispose(): void; - handles(): IIterator; + handles(): IterableIterator; get hiddenMode(): Widget.HiddenMode; set hiddenMode(v: Widget.HiddenMode); hitTestTabAreas(clientX: number, clientY: number): DockLayout.ITabAreaGeometry | null; protected init(): void; get isEmpty(): boolean; - iter(): IIterator; moveHandle(handle: HTMLDivElement, offsetX: number, offsetY: number): void; protected onBeforeAttach(msg: Message): void; protected onBeforeShow(msg: Message): void; @@ -305,11 +303,11 @@ export class DockLayout extends Layout { readonly renderer: DockLayout.IRenderer; restoreLayout(config: DockLayout.ILayoutConfig): void; saveLayout(): DockLayout.ILayoutConfig; - selectedWidgets(): IIterator; + selectedWidgets(): IterableIterator; get spacing(): number; set spacing(value: number); - tabBars(): IIterator>; - widgets(): IIterator; + tabBars(): IterableIterator>; + widgets(): IterableIterator; } // @public @@ -419,7 +417,7 @@ export class DockPanel extends Widget { addWidget(widget: Widget, options?: DockPanel.IAddOptions): void; dispose(): void; handleEvent(event: Event): void; - handles(): IIterator; + handles(): IterableIterator; get hiddenMode(): Widget.HiddenMode; set hiddenMode(v: Widget.HiddenMode); get isEmpty(): boolean; @@ -435,16 +433,16 @@ export class DockPanel extends Widget { get renderer(): DockPanel.IRenderer; restoreLayout(config: DockPanel.ILayoutConfig): void; saveLayout(): DockPanel.ILayoutConfig; - selectedWidgets(): IIterator; + selectedWidgets(): IterableIterator; selectWidget(widget: Widget): void; get spacing(): number; set spacing(value: number); - tabBars(): IIterator>; + tabBars(): IterableIterator>; get tabsConstrained(): boolean; set tabsConstrained(value: boolean); get tabsMovable(): boolean; set tabsMovable(value: boolean); - widgets(): IIterator; + widgets(): IterableIterator; } // @public @@ -534,6 +532,7 @@ export namespace FocusTracker { // @public export class GridLayout extends Layout { + [Symbol.iterator](): IterableIterator; constructor(options?: GridLayout.IOptions); addWidget(widget: Widget): void; protected attachWidget(widget: Widget): void; @@ -545,7 +544,6 @@ export class GridLayout extends Layout { protected detachWidget(widget: Widget): void; dispose(): void; protected init(): void; - iter(): IIterator; protected onBeforeAttach(msg: Message): void; protected onBeforeShow(msg: Message): void; protected onChildHidden(msg: Widget.ChildMessage): void; @@ -582,14 +580,14 @@ export namespace GridLayout { } // @public -export abstract class Layout implements IIterable, IDisposable { +export abstract class Layout implements Iterable, IDisposable { + abstract [Symbol.iterator](): IterableIterator; constructor(options?: Layout.IOptions); dispose(): void; get fitPolicy(): Layout.FitPolicy; set fitPolicy(value: Layout.FitPolicy); protected init(): void; get isDisposed(): boolean; - abstract iter(): IIterator; protected onAfterAttach(msg: Message): void; protected onAfterDetach(msg: Message): void; protected onAfterHide(msg: Message): void; @@ -812,13 +810,13 @@ export namespace Panel { // @public export class PanelLayout extends Layout { + [Symbol.iterator](): IterableIterator; addWidget(widget: Widget): void; protected attachWidget(index: number, widget: Widget): void; protected detachWidget(index: number, widget: Widget): void; dispose(): void; protected init(): void; insertWidget(index: number, widget: Widget): void; - iter(): IIterator; protected moveWidget(fromIndex: number, toIndex: number, widget: Widget): void; removeWidget(widget: Widget): void; removeWidgetAt(index: number): void; @@ -862,11 +860,11 @@ export namespace ScrollBar { // @public export class SingletonLayout extends Layout { + [Symbol.iterator](): IterableIterator; protected attachWidget(widget: Widget): void; protected detachWidget(widget: Widget): void; dispose(): void; protected init(): void; - iter(): IIterator; removeWidget(widget: Widget): void; get widget(): Widget | null; set widget(widget: Widget | null); @@ -1256,7 +1254,7 @@ export class Widget implements IMessageHandler, IObservableDisposable { constructor(options?: Widget.IOptions); activate(): void; addClass(name: string): void; - children(): IIterator; + children(): IterableIterator; clearFlag(flag: Widget.Flag): void; close(): void; contains(widget: Widget): boolean; From 797ea471db1d7caf70ab67859fa0c3f5fdd4581a Mon Sep 17 00:00:00 2001 From: "Afshin T. Darian" Date: Thu, 11 Aug 2022 21:26:13 +0100 Subject: [PATCH 31/62] Fix doc strings --- packages/algorithm/src/sort.ts | 2 +- packages/collections/src/linkedlist.ts | 2 +- packages/disposable/src/index.ts | 4 ++-- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/packages/algorithm/src/sort.ts b/packages/algorithm/src/sort.ts index 7456c5466..401966ce9 100644 --- a/packages/algorithm/src/sort.ts +++ b/packages/algorithm/src/sort.ts @@ -12,7 +12,7 @@ import { each } from './iter'; /** * Topologically sort an iterable of edges. * - * @param edges - The iterable or array-like object of edges to sort. + * @param edges - The iterable object of edges to sort. * An edge is represented as a 2-tuple of `[fromNode, toNode]`. * * @returns The topologically sorted array of nodes. diff --git a/packages/collections/src/linkedlist.ts b/packages/collections/src/linkedlist.ts index 140822cc4..5d24532b7 100644 --- a/packages/collections/src/linkedlist.ts +++ b/packages/collections/src/linkedlist.ts @@ -520,7 +520,7 @@ export namespace LinkedList { /** * Create a linked list from an iterable of values. * - * @param values - The iterable or array-like object of interest. + * @param values - The iterable object of interest. * * @returns A new linked list initialized with the given values. * diff --git a/packages/disposable/src/index.ts b/packages/disposable/src/index.ts index d61c3000f..5c8431d78 100644 --- a/packages/disposable/src/index.ts +++ b/packages/disposable/src/index.ts @@ -192,7 +192,7 @@ export namespace DisposableSet { /** * Create a disposable set from an iterable of items. * - * @param items - The iterable or array-like object of interest. + * @param items - The iterable object of interest. * * @returns A new disposable initialized with the given items. */ @@ -244,7 +244,7 @@ export namespace ObservableDisposableSet { /** * Create an observable disposable set from an iterable of items. * - * @param items - The iterable or array-like object of interest. + * @param items - The iterable object of interest. * * @returns A new disposable initialized with the given items. */ From fbc612a1ed74b36f505d2cda69e16bcb78f649c4 Mon Sep 17 00:00:00 2001 From: "Afshin T. Darian" Date: Sat, 13 Aug 2022 17:10:35 +0100 Subject: [PATCH 32/62] Minor tweak of `LinkedList` iterator methods --- packages/collections/src/linkedlist.ts | 20 ++++++++------------ 1 file changed, 8 insertions(+), 12 deletions(-) diff --git a/packages/collections/src/linkedlist.ts b/packages/collections/src/linkedlist.ts index 5d24532b7..3d8a4045a 100644 --- a/packages/collections/src/linkedlist.ts +++ b/packages/collections/src/linkedlist.ts @@ -108,13 +108,12 @@ export class LinkedList implements Iterable, IRetroable { * Constant. */ [Symbol.iterator](): IterableIterator { - let node = this._first; - return (function* () { + return (function* (node) { while (node) { yield node.value; node = node.next; } - })(); + })(this._first); } /** @@ -126,13 +125,12 @@ export class LinkedList implements Iterable, IRetroable { * Constant. */ retro(): IterableIterator { - let node = this._last; - return (function* () { + return (function* (node) { while (node) { yield node.value; node = node.prev; } - })(); + })(this._last); } /** @@ -144,13 +142,12 @@ export class LinkedList implements Iterable, IRetroable { * Constant. */ nodes(): IterableIterator> { - let node = this._first; - return (function* () { + return (function* (node) { while (node) { yield node; node = node.next; } - })(); + })(this._first); } /** @@ -162,13 +159,12 @@ export class LinkedList implements Iterable, IRetroable { * Constant. */ retroNodes(): IterableIterator> { - let node = this._last; - return (function* () { + return (function* (node) { while (node) { yield node; node = node.prev; } - })(); + })(this._last); } /** From 720ce2ed42feccfd2003771dde89afce3eb42195 Mon Sep 17 00:00:00 2001 From: "Afshin T. Darian" Date: Sat, 13 Aug 2022 18:31:59 +0100 Subject: [PATCH 33/62] Simplify `chain()` --- packages/algorithm/src/chain.ts | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/packages/algorithm/src/chain.ts b/packages/algorithm/src/chain.ts index 8e334ed83..8b479a434 100644 --- a/packages/algorithm/src/chain.ts +++ b/packages/algorithm/src/chain.ts @@ -29,10 +29,9 @@ * ``` */ export function* chain(...objects: Iterable[]) { - for (const obj of objects) { - const it = obj[Symbol.iterator](); - for (let item = it.next(); !item.done; item = it.next()) { - yield item.value; + for (const object of objects) { + for (const item of object) { + yield item; } } } From 35d6f4041974defff4b8b45e1c61ae2fbb1d6fac Mon Sep 17 00:00:00 2001 From: "Afshin T. Darian" Date: Sat, 13 Aug 2022 18:42:15 +0100 Subject: [PATCH 34/62] Simplify `take()` --- packages/algorithm/src/chain.ts | 4 ++-- packages/algorithm/src/enumerate.ts | 4 ++-- packages/algorithm/src/take.ts | 7 ++++--- 3 files changed, 8 insertions(+), 7 deletions(-) diff --git a/packages/algorithm/src/chain.ts b/packages/algorithm/src/chain.ts index 8b479a434..20db1c872 100644 --- a/packages/algorithm/src/chain.ts +++ b/packages/algorithm/src/chain.ts @@ -30,8 +30,8 @@ */ export function* chain(...objects: Iterable[]) { for (const object of objects) { - for (const item of object) { - yield item; + for (const value of object) { + yield value; } } } diff --git a/packages/algorithm/src/enumerate.ts b/packages/algorithm/src/enumerate.ts index 998d2cc9e..9765ff614 100644 --- a/packages/algorithm/src/enumerate.ts +++ b/packages/algorithm/src/enumerate.ts @@ -29,7 +29,7 @@ * ``` */ export function* enumerate(object: Iterable, start = 0) { - for (const item of object) { - yield [start++, item]; + for (const value of object) { + yield [start++, value]; } } diff --git a/packages/algorithm/src/take.ts b/packages/algorithm/src/take.ts index 4ac50d2fa..021408017 100644 --- a/packages/algorithm/src/take.ts +++ b/packages/algorithm/src/take.ts @@ -32,8 +32,9 @@ * ``` */ export function* take(object: Iterable, count: number) { - const it = object[Symbol.iterator](); - for (let item = it.next(); !item.done && 0 < count--; item = it.next()) { - yield item.value; + for (const value of object) { + if (0 < count--) { + yield value; + } } } From 050daeb054fa7dc4ca777100def253af91f80472 Mon Sep 17 00:00:00 2001 From: "Afshin T. Darian" Date: Sat, 13 Aug 2022 18:50:06 +0100 Subject: [PATCH 35/62] [Symbol.iterator]() and Array.from() should almost never need invoked --- packages/collections/tests/src/linkedlist.spec.ts | 2 +- packages/widgets/tests/src/layout.spec.ts | 5 ++--- packages/widgets/tests/src/panellayout.spec.ts | 9 +++++---- 3 files changed, 8 insertions(+), 8 deletions(-) diff --git a/packages/collections/tests/src/linkedlist.spec.ts b/packages/collections/tests/src/linkedlist.spec.ts index 568d9040d..2ee372603 100644 --- a/packages/collections/tests/src/linkedlist.spec.ts +++ b/packages/collections/tests/src/linkedlist.spec.ts @@ -98,7 +98,7 @@ describe('@lumino/collections', () => { }); }); - describe('@@iterator()', () => { + describe('[Symbol.iterator]()', () => { it('should return an iterator over the list values', () => { let data = [0, 1, 2, 3, 4, 5]; let list = LinkedList.from(data); diff --git a/packages/widgets/tests/src/layout.spec.ts b/packages/widgets/tests/src/layout.spec.ts index 7aeeae16b..2696cf7f8 100644 --- a/packages/widgets/tests/src/layout.spec.ts +++ b/packages/widgets/tests/src/layout.spec.ts @@ -91,7 +91,7 @@ class LogLayout extends Layout { describe('@lumino/widgets', () => { describe('Layout', () => { - describe('#iter()', () => { + describe('[Symbol.iterator]()', () => { it('should create an iterator over the widgets in the layout', () => { let layout = new LogLayout(); expect(every(layout, child => child instanceof Widget)).to.equal(true); @@ -113,10 +113,9 @@ describe('@lumino/widgets', () => { let widget = new Widget(); let layout = new LogLayout(); widget.layout = layout; - let children = Array.from(widget.children()); layout.dispose(); expect(layout.parent).to.equal(null); - expect(every(children, w => w.isDisposed)).to.equal(true); + expect(every(widget.children(), w => w.isDisposed)).to.equal(true); }); it('should be called automatically when the parent is disposed', () => { diff --git a/packages/widgets/tests/src/panellayout.spec.ts b/packages/widgets/tests/src/panellayout.spec.ts index 23bda9a0f..911b9b91a 100644 --- a/packages/widgets/tests/src/panellayout.spec.ts +++ b/packages/widgets/tests/src/panellayout.spec.ts @@ -87,7 +87,7 @@ describe('@lumino/widgets', () => { }); }); - describe('#iter()', () => { + describe('[Symbol.iterator]()', () => { it('should create an iterator over the widgets in the layout', () => { let layout = new PanelLayout(); let widgets = [new Widget(), new Widget()]; @@ -97,9 +97,10 @@ describe('@lumino/widgets', () => { each(widgets, w => { w.title.label = 'foo'; }); - let iter = layout[Symbol.iterator](); - expect(every(iter, w => w.title.label === 'foo')).to.equal(true); - expect(layout[Symbol.iterator]()).to.not.equal(iter); + expect(every(layout, w => w.title.label === 'foo')).to.equal(true); + let it1 = layout[Symbol.iterator](), + it2 = layout[Symbol.iterator](); + expect(it1).to.not.equal(it2); }); }); From d6012a40dd66086eac6d9704bbed0a02d2731d44 Mon Sep 17 00:00:00 2001 From: "Afshin T. Darian" Date: Sat, 13 Aug 2022 19:00:55 +0100 Subject: [PATCH 36/62] Third parameter for comparator functions is superfluous when they are iterables --- packages/algorithm/src/iter.ts | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/packages/algorithm/src/iter.ts b/packages/algorithm/src/iter.ts index 2d4eed70e..ea9982dbd 100644 --- a/packages/algorithm/src/iter.ts +++ b/packages/algorithm/src/iter.ts @@ -33,11 +33,11 @@ */ export function each( object: Iterable, - fn: (value: T, index: number, object: Iterable) => boolean | void + fn: (value: T, index: number) => boolean | void ): void { let index = 0; for (const value of object) { - if (false === fn(value, index++, object)) { + if (false === fn(value, index++)) { return; } } @@ -70,11 +70,11 @@ export function each( */ export function every( object: Iterable, - fn: (value: T, index: number, object: Iterable) => boolean + fn: (value: T, index: number) => boolean ): boolean { let index = 0; for (const value of object) { - if (false === fn(value, index++, object)) { + if (false === fn(value, index++)) { return false; } } @@ -108,11 +108,11 @@ export function every( */ export function some( object: Iterable, - fn: (value: T, index: number, object: Iterable) => boolean + fn: (value: T, index: number) => boolean ): boolean { let index = 0; for (const value of object) { - if (fn(value, index++, object)) { + if (fn(value, index++)) { return true; } } From 0f2ec49741818b31340178f8f18aa366822ac447 Mon Sep 17 00:00:00 2001 From: "Afshin T. Darian" Date: Sat, 13 Aug 2022 22:13:13 +0100 Subject: [PATCH 37/62] Simplify stride() --- packages/algorithm/src/stride.ts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/packages/algorithm/src/stride.ts b/packages/algorithm/src/stride.ts index ec5cffe55..c4babd5b4 100644 --- a/packages/algorithm/src/stride.ts +++ b/packages/algorithm/src/stride.ts @@ -30,10 +30,10 @@ * ``` */ export function* stride(object: Iterable, step: number) { - const it = object[Symbol.iterator](); - for (let count = 0, item = it.next(); !item.done; item = it.next()) { + let count = 0; + for (const value of object) { if (0 === count++ % step) { - yield item.value; + yield value; } } } From 68eb1dd45b6772ef54451a6f25adf772ea58a539 Mon Sep 17 00:00:00 2001 From: "Afshin T. Darian" Date: Sat, 13 Aug 2022 22:14:15 +0100 Subject: [PATCH 38/62] Re-enable zip() tests --- packages/algorithm/tests/src/index.spec.ts | 1 + packages/algorithm/tests/src/zip.spec.ts | 13 +++++++------ 2 files changed, 8 insertions(+), 6 deletions(-) diff --git a/packages/algorithm/tests/src/index.spec.ts b/packages/algorithm/tests/src/index.spec.ts index 1abf2a5ef..bbe99fce3 100644 --- a/packages/algorithm/tests/src/index.spec.ts +++ b/packages/algorithm/tests/src/index.spec.ts @@ -22,3 +22,4 @@ import './sort.spec'; import './stride.spec'; import './string.spec'; import './take.spec'; +import './zip.spec'; diff --git a/packages/algorithm/tests/src/zip.spec.ts b/packages/algorithm/tests/src/zip.spec.ts index ba75b03a1..66fec2571 100644 --- a/packages/algorithm/tests/src/zip.spec.ts +++ b/packages/algorithm/tests/src/zip.spec.ts @@ -27,14 +27,15 @@ describe('@lumino/algorithm', () => { describe('zip()', () => { testIterator(() => { - let i1 = ['one', 'two']; - let i2 = [1, 2]; - let i3 = [true, false]; - type T = string | number | boolean; + let i1 = ['one', 'two', 'three', 'four']; + let i2 = [true, false, true]; + let i3 = [1, 2, 3, 4]; + type T = string | boolean | number; let it = zip(i1, i2, i3); let results = [ - ['one', 1, true], - ['two', 2, false] + ['one', true, 1], + ['two', false, 2], + ['three', true, 3] ]; return [it, results]; }); From a5bc2c35a5e6de805bde1dcf973951c6da7345d2 Mon Sep 17 00:00:00 2001 From: "Afshin T. Darian" Date: Sat, 13 Aug 2022 22:22:12 +0100 Subject: [PATCH 39/62] Simplify iterating through selections in data grid. --- packages/datagrid/src/basickeyhandler.ts | 6 +----- packages/datagrid/src/datagrid.ts | 6 +----- 2 files changed, 2 insertions(+), 10 deletions(-) diff --git a/packages/datagrid/src/basickeyhandler.ts b/packages/datagrid/src/basickeyhandler.ts index e47befb55..a92ca401d 100644 --- a/packages/datagrid/src/basickeyhandler.ts +++ b/packages/datagrid/src/basickeyhandler.ts @@ -758,12 +758,8 @@ export class BasicKeyHandler implements DataGrid.IKeyHandler { let maxRow = dataModel.rowCount('body') - 1; let maxColumn = dataModel.columnCount('body') - 1; - const it = grid.selectionModel!.selections(); - let r: IteratorResult; - let s: SelectionModel.Selection | undefined; - while (!(r = it.next()).done) { + for (let s of grid.selectionModel!.selections()) { // Clamp the cell to the model bounds. - s = r.value; let sr1 = Math.max(0, Math.min(s.r1, maxRow)); let sc1 = Math.max(0, Math.min(s.c1, maxColumn)); let sr2 = Math.max(0, Math.min(s.r2, maxRow)); diff --git a/packages/datagrid/src/datagrid.ts b/packages/datagrid/src/datagrid.ts index e685ba2e5..ed0c69fc9 100644 --- a/packages/datagrid/src/datagrid.ts +++ b/packages/datagrid/src/datagrid.ts @@ -5192,12 +5192,8 @@ export class DataGrid extends Widget { } // Iterate over the selections. - let it = model.selections(); - let r: IteratorResult; - let s: SelectionModel.Selection | undefined; - while (!(r = it.next()).done) { + for (let s of model.selections()) { // Skip the section if it's not visible. - s = r.value; if (s.r1 < r1 && s.r2 < r1) { continue; } From f0189cc850220f6001774ceccd01778d43534baa Mon Sep 17 00:00:00 2001 From: "Afshin T. Darian" Date: Sat, 13 Aug 2022 23:18:16 +0100 Subject: [PATCH 40/62] Tweak retro() for readability --- packages/algorithm/src/retro.ts | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/packages/algorithm/src/retro.ts b/packages/algorithm/src/retro.ts index 86f9b580d..34163d378 100644 --- a/packages/algorithm/src/retro.ts +++ b/packages/algorithm/src/retro.ts @@ -44,9 +44,9 @@ export function retro( if (typeof (object as any).retro === 'function') { return (object as IRetroable).retro(); } - return (function* () { - for (let index = (object as ArrayLike).length - 1; ~index; index--) { - yield (object as ArrayLike)[index]; + return (function* (object) { + for (let index = object.length - 1; ~index; index--) { + yield object[index]; } - })(); + })(object as ArrayLike); } From 8a9574a77a571de637543e00270d7de8d6b88eeb Mon Sep 17 00:00:00 2001 From: "Afshin T. Darian" Date: Sun, 14 Aug 2022 19:30:36 +0100 Subject: [PATCH 41/62] Use for...of for minmax() --- packages/algorithm/src/find.ts | 26 +++++++++++++------------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/packages/algorithm/src/find.ts b/packages/algorithm/src/find.ts index 64caf1885..e6ae7ef74 100644 --- a/packages/algorithm/src/find.ts +++ b/packages/algorithm/src/find.ts @@ -220,19 +220,19 @@ export function minmax( object: Iterable, fn: (first: T, second: T) => number ): [T, T] | undefined { - const it = object[Symbol.iterator](); - let item = it.next(); - if (item.done) { - return undefined; - } - let vmin = item.value; - let vmax = item.value; - while (!(item = it.next()).done) { - if (fn(item.value, vmin) < 0) { - vmin = item.value; - } else if (fn(item.value, vmax) > 0) { - vmax = item.value; + let empty = true; + let vmin: T; + let vmax: T; + for (const value of object) { + if (empty) { + vmin = value; + vmax = value; + empty = false; + } else if (fn(value, vmin!) < 0) { + vmin = value; + } else if (fn(value, vmax!) > 0) { + vmax = value; } } - return [vmin, vmax]; + return empty ? undefined : [vmin!, vmax!]; } From fbf1317b55c95dbc69dcd440883439cb793d4e8a Mon Sep 17 00:00:00 2001 From: "Afshin T. Darian" Date: Mon, 15 Aug 2022 00:45:19 +0100 Subject: [PATCH 42/62] Use `IterableIterator` as return type for all generators --- packages/algorithm/src/chain.ts | 2 +- packages/algorithm/src/empty.ts | 2 +- packages/algorithm/src/enumerate.ts | 5 ++++- packages/algorithm/src/filter.ts | 2 +- packages/algorithm/src/map.ts | 2 +- packages/algorithm/src/range.ts | 6 +++++- packages/algorithm/src/repeat.ts | 4 ++-- packages/algorithm/src/stride.ts | 5 ++++- packages/algorithm/src/take.ts | 5 ++++- packages/algorithm/src/zip.ts | 2 +- 10 files changed, 24 insertions(+), 11 deletions(-) diff --git a/packages/algorithm/src/chain.ts b/packages/algorithm/src/chain.ts index 20db1c872..18e6844c7 100644 --- a/packages/algorithm/src/chain.ts +++ b/packages/algorithm/src/chain.ts @@ -28,7 +28,7 @@ * Array.from(stream); // [1, 2, 3, 4, 5, 6] * ``` */ -export function* chain(...objects: Iterable[]) { +export function* chain(...objects: Iterable[]): IterableIterator { for (const object of objects) { for (const value of object) { yield value; diff --git a/packages/algorithm/src/empty.ts b/packages/algorithm/src/empty.ts index a7c580382..2bb1c3d19 100644 --- a/packages/algorithm/src/empty.ts +++ b/packages/algorithm/src/empty.ts @@ -23,6 +23,6 @@ * ``` */ // eslint-disable-next-line require-yield, @typescript-eslint/no-unused-vars -export function* empty() { +export function* empty(): IterableIterator { return; } diff --git a/packages/algorithm/src/enumerate.ts b/packages/algorithm/src/enumerate.ts index 9765ff614..6ab1347be 100644 --- a/packages/algorithm/src/enumerate.ts +++ b/packages/algorithm/src/enumerate.ts @@ -28,7 +28,10 @@ * Array.from(stream); // [[1, 'foo'], [2, 'bar'], [3, 'baz']] * ``` */ -export function* enumerate(object: Iterable, start = 0) { +export function* enumerate( + object: Iterable, + start = 0 +): IterableIterator<[number, T]> { for (const value of object) { yield [start++, value]; } diff --git a/packages/algorithm/src/filter.ts b/packages/algorithm/src/filter.ts index 2eee493f9..e0d9ac873 100644 --- a/packages/algorithm/src/filter.ts +++ b/packages/algorithm/src/filter.ts @@ -31,7 +31,7 @@ export function* filter( object: Iterable, fn: (value: T, index: number) => boolean -) { +): IterableIterator { let index = 0; for (const value of object) { if (fn(value, index++)) { diff --git a/packages/algorithm/src/map.ts b/packages/algorithm/src/map.ts index 575416993..59469e396 100644 --- a/packages/algorithm/src/map.ts +++ b/packages/algorithm/src/map.ts @@ -30,7 +30,7 @@ export function* map( object: Iterable, fn: (value: T, index: number) => U -) { +): IterableIterator { let index = 0; for (const value of object) { yield fn(value, index++); diff --git a/packages/algorithm/src/range.ts b/packages/algorithm/src/range.ts index cc314e31a..e3df6c3c1 100644 --- a/packages/algorithm/src/range.ts +++ b/packages/algorithm/src/range.ts @@ -34,7 +34,11 @@ * Array.from(stream); // [2, 3] * ``` */ -export function* range(start: number, stop?: number, step?: number) { +export function* range( + start: number, + stop?: number, + step?: number +): IterableIterator { if (stop === undefined) { stop = start; start = 0; diff --git a/packages/algorithm/src/repeat.ts b/packages/algorithm/src/repeat.ts index a2869cbd9..499736713 100644 --- a/packages/algorithm/src/repeat.ts +++ b/packages/algorithm/src/repeat.ts @@ -26,7 +26,7 @@ * Array.from(stream); // [7, 7, 7] * ``` */ -export function* repeat(value: T, count: number) { +export function* repeat(value: T, count: number): IterableIterator { while (0 < count--) { yield value; } @@ -48,6 +48,6 @@ export function* repeat(value: T, count: number) { * Array.from(stream); // [7] * ``` */ -export function* once(value: T) { +export function* once(value: T): IterableIterator { yield value; } diff --git a/packages/algorithm/src/stride.ts b/packages/algorithm/src/stride.ts index c4babd5b4..e32e385ef 100644 --- a/packages/algorithm/src/stride.ts +++ b/packages/algorithm/src/stride.ts @@ -29,7 +29,10 @@ * Array.from(stream); // [1, 3, 5]; * ``` */ -export function* stride(object: Iterable, step: number) { +export function* stride( + object: Iterable, + step: number +): IterableIterator { let count = 0; for (const value of object) { if (0 === count++ % step) { diff --git a/packages/algorithm/src/take.ts b/packages/algorithm/src/take.ts index 021408017..f62b3a302 100644 --- a/packages/algorithm/src/take.ts +++ b/packages/algorithm/src/take.ts @@ -31,7 +31,10 @@ * Array.from(stream); // [5, 4, 3] * ``` */ -export function* take(object: Iterable, count: number) { +export function* take( + object: Iterable, + count: number +): IterableIterator { for (const value of object) { if (0 < count--) { yield value; diff --git a/packages/algorithm/src/zip.ts b/packages/algorithm/src/zip.ts index c3f09fe7b..c426b2b86 100644 --- a/packages/algorithm/src/zip.ts +++ b/packages/algorithm/src/zip.ts @@ -30,7 +30,7 @@ import { every } from './iter'; * Array.from(stream); // [[1, 4], [2, 5], [3, 6]] * ``` */ -export function* zip(...objects: Iterable[]) { +export function* zip(...objects: Iterable[]): IterableIterator { const iters = objects.map(obj => obj[Symbol.iterator]()); let tuple = iters.map(it => it.next()); for (; every(tuple, item => !item.done); tuple = iters.map(it => it.next())) { From 654aef5f8ea93592d43af214f80c954cb94629ef Mon Sep 17 00:00:00 2001 From: "Afshin T. Darian" Date: Mon, 15 Aug 2022 08:58:26 +0100 Subject: [PATCH 43/62] Use for...of instead of each() in disposable and update generated API --- packages/disposable/package.json | 1 - packages/disposable/src/index.ts | 10 ++++------ 2 files changed, 4 insertions(+), 7 deletions(-) diff --git a/packages/disposable/package.json b/packages/disposable/package.json index b0e3fd3f1..4b8df7215 100644 --- a/packages/disposable/package.json +++ b/packages/disposable/package.json @@ -40,7 +40,6 @@ "watch": "tsc --build --watch" }, "dependencies": { - "@lumino/algorithm": "^1.9.1", "@lumino/signaling": "^1.10.1" }, "devDependencies": { diff --git a/packages/disposable/src/index.ts b/packages/disposable/src/index.ts index 5c8431d78..d9cc31476 100644 --- a/packages/disposable/src/index.ts +++ b/packages/disposable/src/index.ts @@ -7,8 +7,6 @@ | | The full license is in the file LICENSE, distributed with this software. |----------------------------------------------------------------------------*/ -import { each } from '@lumino/algorithm'; - import { ISignal, Signal } from '@lumino/signaling'; /** @@ -198,9 +196,9 @@ export namespace DisposableSet { */ export function from(items: Iterable): DisposableSet { let set = new DisposableSet(); - each(items, item => { + for (const item of items) { set.add(item); - }); + } return set; } } @@ -250,9 +248,9 @@ export namespace ObservableDisposableSet { */ export function from(items: Iterable): ObservableDisposableSet { let set = new ObservableDisposableSet(); - each(items, item => { + for (const item of items) { set.add(item); - }); + } return set; } } From 14aa4da15809e18d06764b77ebc7c1e645d49e45 Mon Sep 17 00:00:00 2001 From: "Afshin T. Darian" Date: Mon, 15 Aug 2022 09:02:34 +0100 Subject: [PATCH 44/62] Use for...of instead of each() in LinkedList and topologicSort --- packages/algorithm/src/sort.ts | 9 +++++---- packages/collections/src/linkedlist.ts | 6 +++--- 2 files changed, 8 insertions(+), 7 deletions(-) diff --git a/packages/algorithm/src/sort.ts b/packages/algorithm/src/sort.ts index 401966ce9..abf2f7669 100644 --- a/packages/algorithm/src/sort.ts +++ b/packages/algorithm/src/sort.ts @@ -7,7 +7,6 @@ | | The full license is in the file LICENSE, distributed with this software. |----------------------------------------------------------------------------*/ -import { each } from './iter'; /** * Topologically sort an iterable of edges. @@ -42,12 +41,14 @@ export function topologicSort(edges: Iterable<[T, T]>): T[] { let graph = new Map(); // Add the edges to the graph. - each(edges, addEdge); + for (const edge of edges) { + addEdge(edge); + } // Visit each node in the graph. - graph.forEach((v, k) => { + for (const [k] of graph) { visit(k); - }); + } // Return the sorted results. return sorted; diff --git a/packages/collections/src/linkedlist.ts b/packages/collections/src/linkedlist.ts index 3d8a4045a..45666116f 100644 --- a/packages/collections/src/linkedlist.ts +++ b/packages/collections/src/linkedlist.ts @@ -7,7 +7,7 @@ | | The full license is in the file LICENSE, distributed with this software. |----------------------------------------------------------------------------*/ -import { each, IRetroable } from '@lumino/algorithm'; +import { IRetroable } from '@lumino/algorithm'; /** * A generic doubly-linked list. @@ -177,9 +177,9 @@ export class LinkedList implements Iterable, IRetroable { */ assign(values: Iterable): void { this.clear(); - each(values, value => { + for (const value of values) { this.addLast(value); - }); + } } /** From eba5225bc05460dbb47c1d469f6d1ca4d0945359 Mon Sep 17 00:00:00 2001 From: "Afshin T. Darian" Date: Mon, 15 Aug 2022 09:10:52 +0100 Subject: [PATCH 45/62] Use for...of instead of each in signaling --- packages/signaling/src/index.ts | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/packages/signaling/src/index.ts b/packages/signaling/src/index.ts index 4b1d6234e..1dd57f923 100644 --- a/packages/signaling/src/index.ts +++ b/packages/signaling/src/index.ts @@ -7,7 +7,7 @@ | | The full license is in the file LICENSE, distributed with this software. |----------------------------------------------------------------------------*/ -import { ArrayExt, each, find } from '@lumino/algorithm'; +import { ArrayExt, find } from '@lumino/algorithm'; /** * A type alias for a slot function. @@ -416,17 +416,17 @@ namespace Private { } // Clear each connection between the sender and receiver. - each(senders, connection => { + for (const connection of senders) { // Skip connections which have already been cleared. if (!connection.signal) { - return; + continue; } // Clear the connection if it matches the sender. if (connection.signal.sender === sender) { connection.signal = null; } - }); + } // Schedule a cleanup of the senders and receivers. scheduleCleanup(receivers); @@ -446,10 +446,10 @@ namespace Private { } // Clear each receiver connection. - each(receivers, connection => { + for (const connection of receivers) { // Skip connections which have already been cleared. if (!connection.signal) { - return; + continue; } // Choose the best object for the receiver. @@ -460,7 +460,7 @@ namespace Private { // Cleanup the array of senders, which is now known to exist. scheduleCleanup(sendersForReceiver.get(receiver)!); - }); + } // Schedule a cleanup of the receivers. scheduleCleanup(receivers); @@ -479,10 +479,10 @@ namespace Private { } // Clear each sender connection. - each(senders, connection => { + for (const connection of senders) { // Skip connections which have already been cleared. if (!connection.signal) { - return; + continue; } // Lookup the sender for the connection. @@ -493,7 +493,7 @@ namespace Private { // Cleanup the array of receivers, which is now known to exist. scheduleCleanup(receiversForSender.get(sender)!); - }); + } // Schedule a cleanup of the list of senders. scheduleCleanup(senders); From 688cb0f6b91ea947d96afafa11d0294b9cf73bdc Mon Sep 17 00:00:00 2001 From: "Afshin T. Darian" Date: Mon, 15 Aug 2022 09:12:46 +0100 Subject: [PATCH 46/62] Use for...of instead of each() in messaging --- packages/messaging/src/index.ts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/packages/messaging/src/index.ts b/packages/messaging/src/index.ts index d72a68129..0602758b0 100644 --- a/packages/messaging/src/index.ts +++ b/packages/messaging/src/index.ts @@ -7,7 +7,7 @@ | | The full license is in the file LICENSE, distributed with this software. |----------------------------------------------------------------------------*/ -import { ArrayExt, each, every, retro, some } from '@lumino/algorithm'; +import { ArrayExt, every, retro, some } from '@lumino/algorithm'; import { LinkedList } from '@lumino/collections'; @@ -366,12 +366,12 @@ export namespace MessageLoop { } // Clear all posted messages for the handler. - each(messageQueue, posted => { + for (const posted of messageQueue) { if (posted.handler === handler) { posted.handler = null; posted.msg = null; } - }); + } } /** From ad8e19b7c125fdac3230bcac1a546963d2f3db3b Mon Sep 17 00:00:00 2001 From: "Afshin T. Darian" Date: Mon, 15 Aug 2022 09:52:22 +0100 Subject: [PATCH 47/62] In almost all cases, prefer native for..of or .forEach to Lumino utilities --- packages/widgets/src/boxlayout.ts | 6 +- packages/widgets/src/contextmenu.ts | 6 +- packages/widgets/src/docklayout.ts | 92 ++++++++++++------------- packages/widgets/src/dockpanel.ts | 18 ++--- packages/widgets/src/focustracker.ts | 12 ++-- packages/widgets/src/gridlayout.ts | 10 +-- packages/widgets/src/layout.ts | 46 ++++++------- packages/widgets/src/singletonlayout.ts | 6 +- packages/widgets/src/splitlayout.ts | 6 +- packages/widgets/src/stackedlayout.ts | 6 +- packages/widgets/src/tabbar.ts | 6 +- 11 files changed, 103 insertions(+), 111 deletions(-) diff --git a/packages/widgets/src/boxlayout.ts b/packages/widgets/src/boxlayout.ts index 558c05801..331c323d0 100644 --- a/packages/widgets/src/boxlayout.ts +++ b/packages/widgets/src/boxlayout.ts @@ -7,7 +7,7 @@ | | The full license is in the file LICENSE, distributed with this software. |----------------------------------------------------------------------------*/ -import { ArrayExt, each } from '@lumino/algorithm'; +import { ArrayExt } from '@lumino/algorithm'; import { ElementExt } from '@lumino/domutils'; @@ -52,9 +52,9 @@ export class BoxLayout extends PanelLayout { */ dispose(): void { // Dispose of the layout items. - each(this._items, item => { + for (const item of this._items) { item.dispose(); - }); + } // Clear the layout state. this._box = null; diff --git a/packages/widgets/src/contextmenu.ts b/packages/widgets/src/contextmenu.ts index d62ea1ab5..a3fd006e1 100644 --- a/packages/widgets/src/contextmenu.ts +++ b/packages/widgets/src/contextmenu.ts @@ -7,7 +7,7 @@ | | The full license is in the file LICENSE, distributed with this software. |----------------------------------------------------------------------------*/ -import { ArrayExt, each } from '@lumino/algorithm'; +import { ArrayExt } from '@lumino/algorithm'; import { CommandRegistry } from '@lumino/commands'; @@ -100,9 +100,9 @@ export class ContextMenu { } // Add the filtered items to the menu. - each(items, item => { + for (const item of items) { this.menu.addItem(item); - }); + } // Open the context menu at the current mouse position. this.menu.open(event.clientX, event.clientY); diff --git a/packages/widgets/src/docklayout.ts b/packages/widgets/src/docklayout.ts index 6995153af..bb4a1523b 100644 --- a/packages/widgets/src/docklayout.ts +++ b/packages/widgets/src/docklayout.ts @@ -7,15 +7,7 @@ | | The full license is in the file LICENSE, distributed with this software. |----------------------------------------------------------------------------*/ -import { - ArrayExt, - chain, - each, - empty, - map, - once, - reduce -} from '@lumino/algorithm'; +import { ArrayExt, chain, empty, map, once } from '@lumino/algorithm'; import { ElementExt } from '@lumino/domutils'; @@ -79,9 +71,9 @@ export class DockLayout extends Layout { this._items.clear(); // Dispose of the widgets contained in the old layout root. - each(widgets, widget => { + for (const widget of widgets) { widget.dispose(); - }); + } // Dispose of the base class. super.dispose(); @@ -107,13 +99,13 @@ export class DockLayout extends Layout { return; } this._hiddenMode = v; - each(this.tabBars(), bar => { + for (const bar of this.tabBars()) { if (bar.titles.length > 1) { - bar.titles.forEach(title => { + for (const title of bar.titles) { title.owner.hiddenMode = this._hiddenMode; - }); + } } - }); + } } /** @@ -313,28 +305,28 @@ export class DockLayout extends Layout { this._root = null; // Unparent the old widgets which are not in the new config. - each(oldWidgets, widget => { + for (const widget of oldWidgets) { if (!widgetSet.has(widget)) { widget.parent = null; } - }); + } // Dispose of the old tab bars. - each(oldTabBars, tabBar => { + for (const tabBar of oldTabBars) { tabBar.dispose(); - }); + } // Remove the old handles. - each(oldHandles, handle => { + for (const handle of oldHandles) { if (handle.parentNode) { handle.parentNode.removeChild(handle); } - }); + } // Reparent the new widgets to the current parent. - widgetSet.forEach(widget => { + for (const widget of widgetSet) { widget.parent = this.parent; - }); + } // Create the root node for the new config. if (mainConfig) { @@ -518,14 +510,14 @@ export class DockLayout extends Layout { super.init(); // Attach each widget to the parent. - each(this, widget => { + for (const widget of this) { this.attachWidget(widget); - }); + } // Attach each handle to the parent. - each(this.handles(), handle => { + for (const handle of this.handles()) { this.parent!.node.appendChild(handle); - }); + } // Post a fit request for the parent widget. this.parent!.fit(); @@ -1901,7 +1893,7 @@ namespace Private { * Sync the visibility and orientation of the handles. */ syncHandles(): void { - each(this.handles, (handle, i) => { + this.handles.forEach((handle, i) => { handle.setAttribute('data-orientation', this.orientation); if (i === this.handles.length - 1) { handle.classList.add('lm-mod-hidden'); @@ -1917,9 +1909,9 @@ namespace Private { * This sets the size hint of each sizer to its current size. */ holdSizes(): void { - each(this.sizers, sizer => { + for (const sizer of this.sizers) { sizer.sizeHint = sizer.size; - }); + } } /** @@ -1928,7 +1920,9 @@ namespace Private { * This ignores the sizers of tab layout nodes. */ holdAllSizes(): void { - each(this.children, child => child.holdAllSizes()); + for (const child of this.children) { + child.holdAllSizes(); + } this.holdSizes(); } @@ -1946,17 +1940,17 @@ namespace Private { this.holdSizes(); // Compute the sum of the sizes. - let sum = reduce(this.sizers, (v, sizer) => v + sizer.sizeHint, 0); + let sum = this.sizers.reduce((v, sizer) => v + sizer.sizeHint, 0); // Normalize the sizes based on the sum. if (sum === 0) { - each(this.sizers, sizer => { + for (const sizer of this.sizers) { sizer.size = sizer.sizeHint = 1 / n; - }); + } } else { - each(this.sizers, sizer => { + for (const sizer of this.sizers) { sizer.size = sizer.sizeHint /= sum; - }); + } } // Mark the sizes as normalized. @@ -1977,17 +1971,17 @@ namespace Private { let sizes = this.sizers.map(sizer => sizer.size); // Compute the sum of the sizes. - let sum = reduce(sizes, (v, size) => v + size, 0); + let sum = sizes.reduce((v, size) => v + size, 0); // Normalize the sizes based on the sum. if (sum === 0) { - each(sizes, (size, i) => { + for (let i = sizes.length - 1; i > -1; i--) { sizes[i] = 1 / n; - }); + } } else { - each(sizes, (size, i) => { - sizes[i] = size / sum; - }); + for (let i = sizes.length - 1; i > -1; i--) { + sizes[i] /= sum; + } } // Return the normalized sizes. @@ -2044,9 +2038,9 @@ namespace Private { // De-normalize the sizes if needed. if (this.normalized) { - each(this.sizers, sizer => { + for (const sizer of this.sizers) { sizer.sizeHint *= space; - }); + } this.normalized = false; } @@ -2113,12 +2107,12 @@ namespace Private { let widgets: Widget[] = []; // Filter the config for unique widgets. - each(config.widgets, widget => { + for (const widget of config.widgets) { if (!widgetSet.has(widget)) { widgetSet.add(widget); widgets.push(widget); } - }); + } // Bail if there are no effective widgets. if (widgets.length === 0) { @@ -2193,11 +2187,11 @@ namespace Private { let tabBar = renderer.createTabBar(document); // Hide each widget and add it to the tab bar. - each(config.widgets, widget => { + for (const widget of config.widgets) { widget.hide(); tabBar.addTab(widget.title); Private.addAria(widget, tabBar); - }); + } // Set the current index of the tab bar. tabBar.currentIndex = config.currentIndex; @@ -2218,7 +2212,7 @@ namespace Private { let node = new SplitLayoutNode(config.orientation); // Add each child to the layout node. - each(config.children, (child, i) => { + config.children.forEach((child, i) => { // Create the child data for the layout node. let childNode = realizeAreaConfig(child, renderer, document); let sizer = createSizer(config.sizes[i]); diff --git a/packages/widgets/src/dockpanel.ts b/packages/widgets/src/dockpanel.ts index 761ad749d..53d30590d 100644 --- a/packages/widgets/src/dockpanel.ts +++ b/packages/widgets/src/dockpanel.ts @@ -7,7 +7,7 @@ | | The full license is in the file LICENSE, distributed with this software. |----------------------------------------------------------------------------*/ -import { each, find } from '@lumino/algorithm'; +import { find } from '@lumino/algorithm'; import { MimeData } from '@lumino/coreutils'; @@ -192,9 +192,9 @@ export class DockPanel extends Widget { // Configure the layout for the specified mode. switch (value) { case 'multiple-document': - each(layout.tabBars(), tabBar => { + for (const tabBar of layout.tabBars()) { tabBar.show(); - }); + } break; case 'single-document': layout.restoreLayout(Private.createSingleDocumentConfig(this)); @@ -219,9 +219,9 @@ export class DockPanel extends Widget { */ set tabsMovable(value: boolean) { this._tabsMovable = value; - each(this.tabBars(), tabbar => { - tabbar.tabsMovable = value; - }); + for (const tabBar of this.tabBars()) { + tabBar.tabsMovable = value; + } } /** @@ -250,9 +250,9 @@ export class DockPanel extends Widget { */ set addButtonEnabled(value: boolean) { this._addButtonEnabled = value; - each(this.tabBars(), tabbar => { - tabbar.addButtonEnabled = value; - }); + for (const tabBar of this.tabBars()) { + tabBar.addButtonEnabled = value; + } } /** diff --git a/packages/widgets/src/focustracker.ts b/packages/widgets/src/focustracker.ts index e12a1bb66..c5241833c 100644 --- a/packages/widgets/src/focustracker.ts +++ b/packages/widgets/src/focustracker.ts @@ -7,7 +7,7 @@ | | The full license is in the file LICENSE, distributed with this software. |----------------------------------------------------------------------------*/ -import { ArrayExt, each, filter, find, max } from '@lumino/algorithm'; +import { ArrayExt, find, max } from '@lumino/algorithm'; import { IDisposable } from '@lumino/disposable'; @@ -38,10 +38,10 @@ export class FocusTracker implements IDisposable { Signal.clearData(this); // Remove all event listeners. - each(this._widgets, w => { - w.node.removeEventListener('focus', this, true); - w.node.removeEventListener('blur', this, true); - }); + for (const widget of this._widgets) { + widget.node.removeEventListener('focus', this, true); + widget.node.removeEventListener('blur', this, true); + } // Clear the internal data structures. this._activeWidget = null; @@ -226,7 +226,7 @@ export class FocusTracker implements IDisposable { } // Filter the widgets for those which have had focus. - let valid = filter(this._widgets, w => this._numbers.get(w) !== -1); + let valid = this._widgets.filter(w => this._numbers.get(w) !== -1); // Get the valid widget with the max focus number. let previous = diff --git a/packages/widgets/src/gridlayout.ts b/packages/widgets/src/gridlayout.ts index ac03f0cb8..f9398a165 100644 --- a/packages/widgets/src/gridlayout.ts +++ b/packages/widgets/src/gridlayout.ts @@ -7,7 +7,7 @@ | | The full license is in the file LICENSE, distributed with this software. |----------------------------------------------------------------------------*/ -import { ArrayExt, each, map } from '@lumino/algorithm'; +import { ArrayExt, map } from '@lumino/algorithm'; import { ElementExt } from '@lumino/domutils'; @@ -51,11 +51,11 @@ export class GridLayout extends Layout { */ dispose(): void { // Dispose of the widgets and layout items. - each(this._items, item => { + for (const item of this._items) { let widget = item.widget; item.dispose(); widget.dispose(); - }); + } // Clear the layout state. this._box = null; @@ -357,9 +357,9 @@ export class GridLayout extends Layout { */ protected init(): void { super.init(); - each(this, widget => { + for (const widget of this) { this.attachWidget(widget); - }); + } } /** diff --git a/packages/widgets/src/layout.ts b/packages/widgets/src/layout.ts index 2ec0913cb..296456f87 100644 --- a/packages/widgets/src/layout.ts +++ b/packages/widgets/src/layout.ts @@ -8,8 +8,6 @@ | | The full license is in the file LICENSE, distributed with this software. |----------------------------------------------------------------------------*/ -import { each } from '@lumino/algorithm'; - import { IDisposable } from '@lumino/disposable'; import { ElementExt } from '@lumino/domutils'; @@ -239,9 +237,9 @@ export abstract class Layout implements Iterable, IDisposable { * widget nodes to the parent widget's node. */ protected init(): void { - each(this, widget => { + for (const widget of this) { widget.parent = this.parent; - }); + } } /** @@ -258,9 +256,9 @@ export abstract class Layout implements Iterable, IDisposable { * This may be reimplemented by subclasses as needed. */ protected onResize(msg: Widget.ResizeMessage): void { - each(this, widget => { + for (const widget of this) { MessageLoop.sendMessage(widget, Widget.ResizeMessage.UnknownSize); - }); + } } /** @@ -277,9 +275,9 @@ export abstract class Layout implements Iterable, IDisposable { * This may be reimplemented by subclasses as needed. */ protected onUpdateRequest(msg: Message): void { - each(this, widget => { + for (const widget of this) { MessageLoop.sendMessage(widget, Widget.ResizeMessage.UnknownSize); - }); + } } /** @@ -293,9 +291,9 @@ export abstract class Layout implements Iterable, IDisposable { * This may be reimplemented by subclasses as needed. */ protected onBeforeAttach(msg: Message): void { - each(this, widget => { + for (const widget of this) { MessageLoop.sendMessage(widget, msg); - }); + } } /** @@ -309,9 +307,9 @@ export abstract class Layout implements Iterable, IDisposable { * This may be reimplemented by subclasses as needed. */ protected onAfterAttach(msg: Message): void { - each(this, widget => { + for (const widget of this) { MessageLoop.sendMessage(widget, msg); - }); + } } /** @@ -325,9 +323,9 @@ export abstract class Layout implements Iterable, IDisposable { * This may be reimplemented by subclasses as needed. */ protected onBeforeDetach(msg: Message): void { - each(this, widget => { + for (const widget of this) { MessageLoop.sendMessage(widget, msg); - }); + } } /** @@ -341,9 +339,9 @@ export abstract class Layout implements Iterable, IDisposable { * This may be reimplemented by subclasses as needed. */ protected onAfterDetach(msg: Message): void { - each(this, widget => { + for (const widget of this) { MessageLoop.sendMessage(widget, msg); - }); + } } /** @@ -357,11 +355,11 @@ export abstract class Layout implements Iterable, IDisposable { * This may be reimplemented by subclasses as needed. */ protected onBeforeShow(msg: Message): void { - each(this, widget => { + for (const widget of this) { if (!widget.isHidden) { MessageLoop.sendMessage(widget, msg); } - }); + } } /** @@ -375,11 +373,11 @@ export abstract class Layout implements Iterable, IDisposable { * This may be reimplemented by subclasses as needed. */ protected onAfterShow(msg: Message): void { - each(this, widget => { + for (const widget of this) { if (!widget.isHidden) { MessageLoop.sendMessage(widget, msg); } - }); + } } /** @@ -393,11 +391,11 @@ export abstract class Layout implements Iterable, IDisposable { * This may be reimplemented by subclasses as needed. */ protected onBeforeHide(msg: Message): void { - each(this, widget => { + for (const widget of this) { if (!widget.isHidden) { MessageLoop.sendMessage(widget, msg); } - }); + } } /** @@ -411,11 +409,11 @@ export abstract class Layout implements Iterable, IDisposable { * This may be reimplemented by subclasses as needed. */ protected onAfterHide(msg: Message): void { - each(this, widget => { + for (const widget of this) { if (!widget.isHidden) { MessageLoop.sendMessage(widget, msg); } - }); + } } /** diff --git a/packages/widgets/src/singletonlayout.ts b/packages/widgets/src/singletonlayout.ts index 9cc06c0fc..b84460dd6 100644 --- a/packages/widgets/src/singletonlayout.ts +++ b/packages/widgets/src/singletonlayout.ts @@ -7,7 +7,7 @@ | | The full license is in the file LICENSE, distributed with this software. |----------------------------------------------------------------------------*/ -import { each, empty, once } from '@lumino/algorithm'; +import { empty, once } from '@lumino/algorithm'; import { MessageLoop } from '@lumino/messaging'; @@ -118,9 +118,9 @@ export class SingletonLayout extends Layout { */ protected init(): void { super.init(); - each(this, widget => { + for (const widget of this) { this.attachWidget(widget); - }); + } } /** diff --git a/packages/widgets/src/splitlayout.ts b/packages/widgets/src/splitlayout.ts index 6b71501ec..52702995d 100644 --- a/packages/widgets/src/splitlayout.ts +++ b/packages/widgets/src/splitlayout.ts @@ -7,7 +7,7 @@ | | The full license is in the file LICENSE, distributed with this software. |----------------------------------------------------------------------------*/ -import { ArrayExt, each } from '@lumino/algorithm'; +import { ArrayExt } from '@lumino/algorithm'; import { ElementExt } from '@lumino/domutils'; @@ -53,9 +53,9 @@ export class SplitLayout extends PanelLayout { */ dispose(): void { // Dispose of the layout items. - each(this._items, item => { + for (const item of this._items) { item.dispose(); - }); + } // Clear the layout state. this._box = null; diff --git a/packages/widgets/src/stackedlayout.ts b/packages/widgets/src/stackedlayout.ts index 36bdf535c..b4e952c2f 100644 --- a/packages/widgets/src/stackedlayout.ts +++ b/packages/widgets/src/stackedlayout.ts @@ -7,7 +7,7 @@ | | The full license is in the file LICENSE, distributed with this software. |----------------------------------------------------------------------------*/ -import { ArrayExt, each } from '@lumino/algorithm'; +import { ArrayExt } from '@lumino/algorithm'; import { ElementExt } from '@lumino/domutils'; @@ -69,9 +69,9 @@ export class StackedLayout extends PanelLayout { */ dispose(): void { // Dispose of the layout items. - each(this._items, item => { + for (const item of this._items) { item.dispose(); - }); + } // Clear the layout state. this._box = null; diff --git a/packages/widgets/src/tabbar.ts b/packages/widgets/src/tabbar.ts index 233aa3c91..0f23c23b0 100644 --- a/packages/widgets/src/tabbar.ts +++ b/packages/widgets/src/tabbar.ts @@ -7,7 +7,7 @@ | | The full license is in the file LICENSE, distributed with this software. |----------------------------------------------------------------------------*/ -import { ArrayExt, each } from '@lumino/algorithm'; +import { ArrayExt } from '@lumino/algorithm'; import { IDisposable } from '@lumino/disposable'; @@ -2005,12 +2005,12 @@ namespace Private { tabs: HTMLCollection, orientation: TabBar.Orientation ): void { - each(tabs, tab => { + for (const tab of tabs) { if (orientation === 'horizontal') { (tab as HTMLElement).style.left = ''; } else { (tab as HTMLElement).style.top = ''; } - }); + } } } From 00e68552f2e2970723d451047646138159a5b3d6 Mon Sep 17 00:00:00 2001 From: "Afshin T. Darian" Date: Mon, 15 Aug 2022 10:37:27 +0100 Subject: [PATCH 48/62] Fix examples --- examples/example-dockpanel-amd/src/index.js | 19 +++++++++++-------- examples/example-dockpanel/tsconfig.json | 4 ++-- 2 files changed, 13 insertions(+), 10 deletions(-) diff --git a/examples/example-dockpanel-amd/src/index.js b/examples/example-dockpanel-amd/src/index.js index eeca51a03..9aae018de 100644 --- a/examples/example-dockpanel-amd/src/index.js +++ b/examples/example-dockpanel-amd/src/index.js @@ -53,15 +53,18 @@ define(['@lumino/commands', '@lumino/widgets'], function ( return root; } - function ContentWidget(name) { - Widget.call(this, { node: ContentWidget.prototype.createNode() }); - this.setFlag(Widget.Flag.DisallowLayout); - this.addClass('content'); - this.addClass(name.toLowerCase()); - this.title.label = name; - this.title.closable = true; - this.title.caption = 'Long description for: ' + name; + class ContentWidget extends Widget { + constructor(name) { + super({ node: ContentWidget.prototype.createNode() }); + this.setFlag(Widget.Flag.DisallowLayout); + this.addClass('content'); + this.addClass(name.toLowerCase()); + this.title.label = name; + this.title.closable = true; + this.title.caption = 'Long description for: ' + name; + } } + ContentWidget.prototype = Object.create(Widget.prototype); ContentWidget.prototype.createNode = function () { diff --git a/examples/example-dockpanel/tsconfig.json b/examples/example-dockpanel/tsconfig.json index 8f3f94b49..812ad282c 100644 --- a/examples/example-dockpanel/tsconfig.json +++ b/examples/example-dockpanel/tsconfig.json @@ -8,9 +8,9 @@ "sourceMap": true, "module": "commonjs", "moduleResolution": "node", - "target": "ES5", + "target": "ES6", "outDir": "./build", - "lib": ["ES5", "ES2015.Promise", "ES2015.Iterable", "DOM"], + "lib": ["ES6", "DOM"], "types": [] }, "include": ["src/*"] From b9a0b1bad81d0a33830d40c1d3886652fbeb1ec2 Mon Sep 17 00:00:00 2001 From: "Afshin T. Darian" Date: Mon, 15 Aug 2022 14:50:30 +0100 Subject: [PATCH 49/62] Fine. --- packages/algorithm/src/retro.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/algorithm/src/retro.ts b/packages/algorithm/src/retro.ts index 34163d378..a5583c48e 100644 --- a/packages/algorithm/src/retro.ts +++ b/packages/algorithm/src/retro.ts @@ -45,7 +45,7 @@ export function retro( return (object as IRetroable).retro(); } return (function* (object) { - for (let index = object.length - 1; ~index; index--) { + for (let index = object.length - 1; index > -1; index--) { yield object[index]; } })(object as ArrayLike); From 0f747deda940e54b8faef6ecf6f44dfebe78fd4f Mon Sep 17 00:00:00 2001 From: "Afshin T. Darian" Date: Tue, 16 Aug 2022 11:00:08 +0100 Subject: [PATCH 50/62] Add iteration notes to migration.md --- docs/source/index.rst | 1 + docs/source/migration.md | 142 +++++++++++++++++++++++++++++++++++++++ 2 files changed, 143 insertions(+) create mode 100644 docs/source/migration.md diff --git a/docs/source/index.rst b/docs/source/index.rst index 1f8b7e502..8774dbdc3 100644 --- a/docs/source/index.rst +++ b/docs/source/index.rst @@ -13,6 +13,7 @@ Lumino changelog api examples + migration Indices and tables ================== diff --git a/docs/source/migration.md b/docs/source/migration.md new file mode 100644 index 000000000..5804c8eba --- /dev/null +++ b/docs/source/migration.md @@ -0,0 +1,142 @@ +# Migration guide for Lumino 1 to Lumino 2 + +## Iterables, iterators, and generators + +### Overview and suggestions on iteration + +These are some guiding principles that came up over the course of refactoring the way we handle iteration in Lumino. They are not hard and fast rules, rather they are intuitions that arose while implementing the changes Lumino 2. + +### Use `each(...)` sparingly + +Iterating through an iterable `bar: Iterable` using native `for...of`, e.g., `for (const foo of bar) {...}` is almost always a better option than using `each(bar, foo => ...)`. Some exceptions to this are: + +- When you need the index of an item during iteration and you are _not_ iterating through an array, which already provides the index as a second parameter to a function passed into `.forEach(...)` +- When you could use the array `.forEach(...)` method but you want to be able to terminate iteration early, which you cannot do natively, but can with `each(...)` by returning `false` + +Nearly all invocations of `each(...)` have been removed in Lumino 2 (except for tests). See, for example, [this commit](https://github.com/jupyterlab/lumino/pull/346/commits/efb1e919bb359192caeedb726e16ec42d17b3b0f). + +### Use `[].forEach(...)` sparingly + +Now that we support native ES6 iteration, `for (const value of someArray) {...}` should be favored over `someArray.forEach(...)` because it will not require a context shift every time it invokes the function being applied. + +### Use `[Symbol.iterator]()` sparingly + +Unless you need a handle on multiple iterators simultaneously (e.g., the way `zip(...)` is implemented in Lumino 2) or you need to hold on to multiple values of your iterable during iteration (e.g., the way we need both the first and the second value of an iterable to implement `reduce(...)` in Lumino 2), most of the time you can simply use `for...of` to iterate through any object that has a `Symbol.iterator` method without invoking that method. + +In many places where the Lumino `iter()` utility function has been replaced in Lumino 2 it is not replaced with an invocation of the new `Symbol.iterator` method. + +### Use `Array.from(...)` sparingly + +`toArray(...)` has been removed. You may be tempted to swap in `Array.from(...)` when you update your code. This _will_ work, but if you simply need to iterate through an iterable, you can use `for...of` directly on the iterable object. This is more performant both in terms of CPU and memory than allocating and populating new `Array` instance before iteration. + +If you need a snapshot of every item in your iterable as an array, then `Array.from(...)` is an appropriate replacement for `toArray(...)`. + +## Public API changes + +### `@lumino/algorithm` + +All of the iterator utilities have been changed to use native generators and iterators. + +| | `export` | name | note | +| --- | ----------- | ------------------------ | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| ❌ | `type` | `IterableOrArrayLike` | Switch to [`Iterable`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Iteration_protocols#the_iterable_protocol) | +| ❌ | `interface` | `IIterable` | Switch to `Iterable` | +| ❌ | `interface` | `IIterator` | Switch to [`Iterator`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Iteration_protocols#the_iterator_protocol) / `IterableIterator` | +| ❌ | `function` | `iter(...)` | Switch to [`Symbol.iterator`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Symbol/iterator) and [`function*`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/function*) | +| ❌ | `function` | `iterFn(...)` | Switch to `function*` | +| ❌ | `function` | `iterItems(...)` | We aren't using this function anywhere | +| ❌ | `function` | `iterKeys(...)` | Switch to [`for ... in`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/for...in) | +| ❌ | `function` | `iterValues(...)` | Switch to [`for ... of`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/for...of) | +| ❌ | `function` | `toArray(...)` | Switch to [`Array.from(...)`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/from) | +| ❌ | `function` | `toObject(...)` | We aren't using this function anywhere | +| ❌ | `class` | `ArrayIterator` | Switch to `[][Symbol.iterator]()` | +| ❌ | `class` | `ChainIterator` | Previous implementation of `chain()` | +| ❌ | `class` | `EmptyIterator` | Previous implementation of `empty()` | +| ❌ | `class` | `EnumerateIterator` | Previous implementation of `enumerate()` | +| ❌ | `class` | `FilterIterator` | Previous implementation of `filter()` | +| ❌ | `class` | `FnIterator` | Switch to [generators](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Generator) | +| ❌ | `class` | `ItemIterator` | We aren't using this class anywhere | +| ❌ | `class` | `KeyIterator` | Switch to `for ... in` | +| ❌ | `class` | `MapIterator` | Previous implementation of `map()` | +| ❌ | `class` | `RangeIterator` | Previous implementation of `range()` | +| ❌ | `class` | `RetroIterator` | Previous implementation of `retro()` | +| ❌ | `class` | `StrideIterator` | Previous implementation of `stride()` | +| ❌ | `class` | `TakeIterator` | Previous implementation of `take()` | +| ❌ | `class` | `ValueIterator` | Switch to `for ... of` | +| ❌ | `class` | `ZipIterator` | Previous implementation of `zip()` | +| ✅ | `function` | `chain(...)` | Reimplement with native types | +| ✅ | `function` | `each(...)` | Reimplement with native types | +| ✅ | `function` | `empty(...)` | Reimplement with native types | +| ✅ | `function` | `enumerate(...)` | Reimplement with native types | +| ✅ | `function` | `every(...)` | Reimplement with native types | +| ✅ | `function` | `filter(...)` | Reimplement with native types | +| ✅ | `function` | `find(...)` | Reimplement with native types | +| ✅ | `function` | `findIndex(...)` | Reimplement with native types | +| ✅ | `function` | `map(...)` | Reimplement with native types | +| ✅ | `function` | `max(...)` | Reimplement with native types | +| ✅ | `function` | `min(...)` | Reimplement with native types | +| ✅ | `function` | `minmax(...)` | Support native types | +| ✅ | `function` | `reduce(...)` | Support native types | +| ✅ | `function` | `range(...)` | Reimplement with native types | +| ✅ | `function` | `retro(...)` | Reimplement with native types | +| ✅ | `function` | `some(...)` | Reimplement with native types | +| ✅ | `function` | `stride(...)` | Reimplement with native types | +| ✅ | `function` | `take(...)` | Reimplement with native types | +| ✅ | `function` | `topologicSort(...)` | Support native types | +| ✅ | `function` | `zip(...)` | Reimplement with native types | + +### `@lumino/collections` + +`LinkedList` has been updated to accept native iterables and return native iterators. + +| | `export` | name | note | +| --- | ---------- | --------------------------------- | ---------------------------------------------------- | +| ❌ | `class` | `LinkedList.ForwardValueIterator` | Switch to `LinkedList#[Symbol.iterator]` | +| ❌ | `class` | `LinkedList.RetroValueIterator` | Previous implementation of `LinkedList#retro()` | +| ❌ | `class` | `LinkedList.ForwardNodeIterator` | Previous implementation of `LinkedList#nodes()` | +| ❌ | `class` | `LinkedList.RetroNodeIterator` | Previous implementation of `LinkedList#retroNodes()` | +| ❌ | `method` | `LinkedList#iter()` | Switch to `LinkedList#[Symbol.iterator]` | +| ✅ | `function` | `LinkedList.from(...)` | Accept `Iterable` | +| ✅ | `method` | `LinkedList#assign(...)` | Accept `Iterable` | +| ✅ | `method` | `LinkedList#nodes()` | Return `IterableIterator>` | +| ✅ | `method` | `LinkedList#retro()` | Return `IterableIterator` | +| ✅ | `method` | `LinkedList#retroNodes()` | Return `IterableIterator>` | + +### `@lumino/datagrid` + +`DataGrid` selections are now native iterators. + +| | `export` | name | note | +| --- | -------- | ---------------------------------- | --------------------------------------------------- | +| ✅ | `method` | `BasicSelectionModel#selections()` | Return `IterableIterator` | +| ✅ | `method` | `SelectionModel#selections()` | Return `IterableIterator` | + +### `@lumino/disposable` + +Helper functions for `DisposableSet` and `ObservableDisposableSet` have been udpated. + +| | `export` | name | note | +| --- | ---------- | ----------------------------------- | ------------------------------ | +| ✅ | `function` | `DisposableSet.from(...)` | Accept `Iterable` | +| ✅ | `function` | `ObservableDisposableSet.from(...)` | Accept `Iterable` | + +### `@lumino/widgets` + +`Layout` and its sub-classes now use native iterators, e.g. `implements Iterable`. + +| | `export` | name | note | +| --- | -------- | ------------------------------ | --------------------------------------------- | +| ❌ | `method` | `DockLayout#iter()` | Switch to `DockLayout#[Symbol.iterator]` | +| ❌ | `method` | `GridLayout#iter()` | Switch to `GridLayout#[Symbol.iterator]` | +| ❌ | `method` | `Layout#iter()` | Switch to `Layout#[Symbol.iterator]` | +| ❌ | `method` | `PanelLayout#iter()` | Switch to `PanelLayout#[Symbol.iterator]` | +| ❌ | `method` | `SingletonLayout#iter()` | Switch to `SingletonLayout#[Symbol.iterator]` | +| ✅ | `method` | `DockLayout#handles()` | Return `IterableIterator` | +| ✅ | `method` | `DockLayout#selectedWidgets()` | Return `IterableIterator` | +| ✅ | `method` | `DockLayout#tabBars()` | Return `IterableIterator>` | +| ✅ | `method` | `DockLayout#widgets()` | Return `IterableIterator` | +| ✅ | `method` | `DockPanel#handles()` | Return `IterableIterator` | +| ✅ | `method` | `DockPanel#selectedWidgets()` | Return `IterableIterator` | +| ✅ | `method` | `DockPanel#tabBars()` | Return `IterableIterator>` | +| ✅ | `method` | `DockPanel#widgets()` | Return `IterableIterator` | +| ✅ | `method` | `Widget#children()` | Return `IterableIterator` | From 9caca569a8ed9969162da1a2ee4183360ebba628 Mon Sep 17 00:00:00 2001 From: "Afshin T. Darian" Date: Tue, 16 Aug 2022 13:41:40 +0100 Subject: [PATCH 51/62] Add test for take() where count=0 --- packages/algorithm/tests/src/take.spec.ts | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/packages/algorithm/tests/src/take.spec.ts b/packages/algorithm/tests/src/take.spec.ts index b092a85bf..8295ef7cb 100644 --- a/packages/algorithm/tests/src/take.spec.ts +++ b/packages/algorithm/tests/src/take.spec.ts @@ -23,4 +23,10 @@ describe('@lumino/algorithm', () => { return [take([0, 1, 2, 3][Symbol.iterator](), 1), [0]]; }); }); + + describe('take() with count=0', () => { + testIterator(() => { + return [take([0, 1, 2, 3][Symbol.iterator](), 0), []]; + }); + }); }); From d74f6c2a45f140b128bbb9dad4a22cc0cf72fe05 Mon Sep 17 00:00:00 2001 From: "Afshin T. Darian" Date: Tue, 16 Aug 2022 13:43:01 +0100 Subject: [PATCH 52/62] Remove duplicate repeat() test --- packages/algorithm/tests/src/repeat.spec.ts | 6 ------ 1 file changed, 6 deletions(-) diff --git a/packages/algorithm/tests/src/repeat.spec.ts b/packages/algorithm/tests/src/repeat.spec.ts index 7128ffdab..179ceb300 100644 --- a/packages/algorithm/tests/src/repeat.spec.ts +++ b/packages/algorithm/tests/src/repeat.spec.ts @@ -18,12 +18,6 @@ describe('@lumino/algorithm', () => { }); }); - describe('repeat()', () => { - testIterator(() => { - return [repeat('foo', 3), ['foo', 'foo', 'foo']]; - }); - }); - describe('once()', () => { testIterator(() => { return [once('foo'), ['foo']]; From 929b6d9800357520dcbeb571ca7f3ba864567b18 Mon Sep 17 00:00:00 2001 From: "Afshin T. Darian" Date: Tue, 16 Aug 2022 13:44:22 +0100 Subject: [PATCH 53/62] Better label for stride() test --- packages/algorithm/tests/src/stride.spec.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/algorithm/tests/src/stride.spec.ts b/packages/algorithm/tests/src/stride.spec.ts index fbf0ee586..a51d3e348 100644 --- a/packages/algorithm/tests/src/stride.spec.ts +++ b/packages/algorithm/tests/src/stride.spec.ts @@ -12,13 +12,13 @@ import { stride } from '@lumino/algorithm'; import { testIterator } from './iter.spec'; describe('@lumino/algorithm', () => { - describe('stride()', () => { + describe('stride() with an array', () => { testIterator(() => { return [stride([0, 1, 2, 3, 4, 5], 2), [0, 2, 4]]; }); }); - describe('StrideIterator', () => { + describe('stride() with an iterable iterator', () => { testIterator(() => { let it = [1, 2, 3, 4, 5, 6, 7][Symbol.iterator](); return [stride(it, 3), [1, 4, 7]]; From 1fbfcaebc5922d71ae3117b99aa496a344b1f9f2 Mon Sep 17 00:00:00 2001 From: "Afshin T. Darian" Date: Tue, 16 Aug 2022 13:49:15 +0100 Subject: [PATCH 54/62] Better labels for zip() tests --- packages/algorithm/tests/src/zip.spec.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/algorithm/tests/src/zip.spec.ts b/packages/algorithm/tests/src/zip.spec.ts index 66fec2571..f38ba995e 100644 --- a/packages/algorithm/tests/src/zip.spec.ts +++ b/packages/algorithm/tests/src/zip.spec.ts @@ -12,7 +12,7 @@ import { zip } from '@lumino/algorithm'; import { testIterator } from './iter.spec'; describe('@lumino/algorithm', () => { - describe('zip()', () => { + describe('zip() with same-length iterables', () => { testIterator(() => { return [ zip([1, 2, 3], [4, 5, 6]), @@ -25,7 +25,7 @@ describe('@lumino/algorithm', () => { }); }); - describe('zip()', () => { + describe('zip() with different-length iterables', () => { testIterator(() => { let i1 = ['one', 'two', 'three', 'four']; let i2 = [true, false, true]; From bc2b48f7f0a1bebf3279456fa81e1054b0189644 Mon Sep 17 00:00:00 2001 From: "Afshin T. Darian" Date: Tue, 16 Aug 2022 13:52:49 +0100 Subject: [PATCH 55/62] Clean up test labels as per review comments --- packages/algorithm/tests/src/map.spec.ts | 8 -------- packages/algorithm/tests/src/retro.spec.ts | 8 ++++---- packages/algorithm/tests/src/take.spec.ts | 4 ++-- 3 files changed, 6 insertions(+), 14 deletions(-) diff --git a/packages/algorithm/tests/src/map.spec.ts b/packages/algorithm/tests/src/map.spec.ts index f470513e8..dbfce8c15 100644 --- a/packages/algorithm/tests/src/map.spec.ts +++ b/packages/algorithm/tests/src/map.spec.ts @@ -19,12 +19,4 @@ describe('@lumino/algorithm', () => { return [it, result]; }); }); - - describe('map()', () => { - testIterator(() => { - let result = [0, 1, 8, 27]; - let it = map([0, 1, 2, 3][Symbol.iterator](), x => x ** 3); - return [it, result]; - }); - }); }); diff --git a/packages/algorithm/tests/src/retro.spec.ts b/packages/algorithm/tests/src/retro.spec.ts index 205835682..8c98455bc 100644 --- a/packages/algorithm/tests/src/retro.spec.ts +++ b/packages/algorithm/tests/src/retro.spec.ts @@ -24,11 +24,11 @@ describe('@lumino/algorithm', () => { let retroable = { retro: () => iterator }; expect(retro(retroable)).to.equal(iterator); }); - }); - describe('retro()', () => { - testIterator(() => { - return [retro([1, 2, 3]), [3, 2, 1]]; + it('should reverse an array', () => { + testIterator(() => { + return [retro([1, 2, 3]), [3, 2, 1]]; + }); }); }); }); diff --git a/packages/algorithm/tests/src/take.spec.ts b/packages/algorithm/tests/src/take.spec.ts index 8295ef7cb..83a3828c7 100644 --- a/packages/algorithm/tests/src/take.spec.ts +++ b/packages/algorithm/tests/src/take.spec.ts @@ -12,13 +12,13 @@ import { take } from '@lumino/algorithm'; import { testIterator } from './iter.spec'; describe('@lumino/algorithm', () => { - describe('take()', () => { + describe('take() from an array', () => { testIterator(() => { return [take([1, 2, 3, 4, 5], 2), [1, 2]]; }); }); - describe('take()', () => { + describe('take() from an iterable iterator', () => { testIterator(() => { return [take([0, 1, 2, 3][Symbol.iterator](), 1), [0]]; }); From 84ec11bf5572893e8566a2cf86bf39299afc315d Mon Sep 17 00:00:00 2001 From: "Afshin T. Darian" Date: Tue, 16 Aug 2022 14:55:27 +0100 Subject: [PATCH 56/62] Change rangeLength signature back --- packages/algorithm/src/range.ts | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/packages/algorithm/src/range.ts b/packages/algorithm/src/range.ts index e3df6c3c1..66d1ab0a3 100644 --- a/packages/algorithm/src/range.ts +++ b/packages/algorithm/src/range.ts @@ -67,7 +67,11 @@ namespace Private { * * @returns The number of steps need to traverse the range. */ - export function rangeLength(start: number, stop: number, step: number) { + export function rangeLength( + start: number, + stop: number, + step: number + ): number { if (step === 0) { return Infinity; } From 1442576a565e132f76623bf0a961088037a67827 Mon Sep 17 00:00:00 2001 From: "Afshin T. Darian" Date: Tue, 16 Aug 2022 15:59:34 +0100 Subject: [PATCH 57/62] Reimplement toObject() using iterables and toArray() as a deprecated placeholder for Array.from() --- docs/source/migration.md | 10 +++-- packages/algorithm/src/iter.ts | 50 +++++++++++++++++++++++ packages/algorithm/tests/src/iter.spec.ts | 23 ++++++++++- review/api/algorithm.api.md | 8 ++++ 4 files changed, 87 insertions(+), 4 deletions(-) diff --git a/docs/source/migration.md b/docs/source/migration.md index 5804c8eba..1b0d7d6b6 100644 --- a/docs/source/migration.md +++ b/docs/source/migration.md @@ -27,7 +27,7 @@ In many places where the Lumino `iter()` utility function has been replaced in L ### Use `Array.from(...)` sparingly -`toArray(...)` has been removed. You may be tempted to swap in `Array.from(...)` when you update your code. This _will_ work, but if you simply need to iterate through an iterable, you can use `for...of` directly on the iterable object. This is more performant both in terms of CPU and memory than allocating and populating new `Array` instance before iteration. +`toArray(...)` has been deprecated. You may be tempted to swap in `Array.from(...)` when you update your code. This _will_ work, but if you simply need to iterate through an iterable, you can use `for...of` directly on the iterable object. This is more performant both in terms of CPU and memory than allocating and populating new `Array` instance before iteration. If you need a snapshot of every item in your iterable as an array, then `Array.from(...)` is an appropriate replacement for `toArray(...)`. @@ -82,8 +82,12 @@ All of the iterator utilities have been changed to use native generators and ite | ✅ | `function` | `some(...)` | Reimplement with native types | | ✅ | `function` | `stride(...)` | Reimplement with native types | | ✅ | `function` | `take(...)` | Reimplement with native types | -| ✅ | `function` | `topologicSort(...)` | Support native types | -| ✅ | `function` | `zip(...)` | Reimplement with native types | + +| ☑️ | `function` | `toArray(...)` | `@deprecated`, use [`Array.from(...)`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/from) or [`for ... of`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/for...of) | +| ✅ | `function` | `toObject(...)` | Reimplement with native types | + +| ✅ | `function` | `topologicSort(...)` | Support native types | +| ✅ | `function` | `zip(...)` | Reimplement with native types | ### `@lumino/collections` diff --git a/packages/algorithm/src/iter.ts b/packages/algorithm/src/iter.ts index ea9982dbd..c25f3fce0 100644 --- a/packages/algorithm/src/iter.ts +++ b/packages/algorithm/src/iter.ts @@ -8,6 +8,56 @@ | The full license is in the file LICENSE, distributed with this software. |----------------------------------------------------------------------------*/ +/** + * Create an array from an iterable of values. + * + * @deprecated + * + * @param object - The iterable or array-like object of interest. + * + * @returns A new array of values from the given object. + * + * #### Example + * ```typescript + * import { iter, toArray } from '@lumino/algorithm'; + * + * let data = [1, 2, 3, 4, 5, 6]; + * + * let stream = iter(data); + * + * toArray(stream); // [1, 2, 3, 4, 5, 6]; + * ``` + */ +export function toArray(object: Iterable): T[] { + return Array.from(object); +} + +/** + * Create an object from an iterable of key/value pairs. + * + * @param object - The iterable or array-like object of interest. + * + * @returns A new object mapping keys to values. + * + * #### Example + * ```typescript + * import { toObject } from '@lumino/algorithm'; + * + * let data: [string, number][] = [['one', 1], ['two', 2], ['three', 3]]; + * + * toObject(data); // { one: 1, two: 2, three: 3 } + * ``` + */ +export function toObject(object: Iterable<[string, T]>): { + [key: string]: T; +} { + const result: { [key: string]: T } = {}; + for (const [key, value] of object) { + result[key] = value; + } + return result; +} + /** * Invoke a function for each value in an iterable. * diff --git a/packages/algorithm/tests/src/iter.spec.ts b/packages/algorithm/tests/src/iter.spec.ts index 7bcbc70aa..861af7a03 100644 --- a/packages/algorithm/tests/src/iter.spec.ts +++ b/packages/algorithm/tests/src/iter.spec.ts @@ -9,7 +9,7 @@ |----------------------------------------------------------------------------*/ import { expect } from 'chai'; -import { each, every, some } from '@lumino/algorithm'; +import { each, every, some, toArray, toObject } from '@lumino/algorithm'; /** * A helper function to test the methods of an iterator. @@ -29,6 +29,27 @@ export function testIterator( } describe('@lumino/algorithm', () => { + describe('toArray()', () => { + it('should create an array from an iterable', () => { + let data = [1, 2, 3, 4, 5, 6]; + let stream = data[Symbol.iterator](); + let result = toArray(stream); + expect(result).to.deep.equal([1, 2, 3, 4, 5, 6]); + }); + }); + + describe('toObject()', () => { + it('should create an object from a [key, value] iterable', () => { + let data: [string, number][] = [ + ['one', 1], + ['two', 2], + ['three', 3] + ]; + let result = toObject(data); + expect(result).to.deep.equal({ one: 1, two: 2, three: 3 }); + }); + }); + describe('each()', () => { it('should visit every item in an iterable', () => { let result = 0; diff --git a/review/api/algorithm.api.md b/review/api/algorithm.api.md index 12e184427..f03979016 100644 --- a/review/api/algorithm.api.md +++ b/review/api/algorithm.api.md @@ -128,6 +128,14 @@ export namespace StringExt { // @public export function take(object: Iterable, count: number): IterableIterator; +// @public @deprecated +export function toArray(object: Iterable): T[]; + +// @public +export function toObject(object: Iterable<[string, T]>): { + [key: string]: T; +}; + // @public export function topologicSort(edges: Iterable<[T, T]>): T[]; From da91b289f4c4486534d560d574b1c864a0cb1ed9 Mon Sep 17 00:00:00 2001 From: "Afshin T. Darian" Date: Tue, 16 Aug 2022 16:44:03 +0100 Subject: [PATCH 58/62] Better toObject() test --- packages/algorithm/tests/src/iter.spec.ts | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) diff --git a/packages/algorithm/tests/src/iter.spec.ts b/packages/algorithm/tests/src/iter.spec.ts index 861af7a03..807435ad1 100644 --- a/packages/algorithm/tests/src/iter.spec.ts +++ b/packages/algorithm/tests/src/iter.spec.ts @@ -9,7 +9,7 @@ |----------------------------------------------------------------------------*/ import { expect } from 'chai'; -import { each, every, some, toArray, toObject } from '@lumino/algorithm'; +import { each, every, some, toArray, toObject, zip } from '@lumino/algorithm'; /** * A helper function to test the methods of an iterator. @@ -40,12 +40,10 @@ describe('@lumino/algorithm', () => { describe('toObject()', () => { it('should create an object from a [key, value] iterable', () => { - let data: [string, number][] = [ - ['one', 1], - ['two', 2], - ['three', 3] - ]; - let result = toObject(data); + let keys = ['one', 'two', 'three']; + let values = [1, 2, 3]; + let stream = zip(keys, values); + let result = toObject(stream as Iterable<[string, number]>); expect(result).to.deep.equal({ one: 1, two: 2, three: 3 }); }); }); From c6673e89881e2c9127de6c0333908c522aca5098 Mon Sep 17 00:00:00 2001 From: "Afshin T. Darian" Date: Tue, 16 Aug 2022 20:08:44 +0100 Subject: [PATCH 59/62] Fix logic bug in take() that @vidartf noticed --- packages/algorithm/src/take.ts | 11 +++++++---- packages/algorithm/tests/src/take.spec.ts | 13 +++++++++---- 2 files changed, 16 insertions(+), 8 deletions(-) diff --git a/packages/algorithm/src/take.ts b/packages/algorithm/src/take.ts index f62b3a302..bb12709aa 100644 --- a/packages/algorithm/src/take.ts +++ b/packages/algorithm/src/take.ts @@ -35,9 +35,12 @@ export function* take( object: Iterable, count: number ): IterableIterator { - for (const value of object) { - if (0 < count--) { - yield value; - } + if (count < 1) { + return; + } + const it = object[Symbol.iterator](); + let item: IteratorResult; + while (0 < count-- && !(item = it.next()).done) { + yield item.value; } } diff --git a/packages/algorithm/tests/src/take.spec.ts b/packages/algorithm/tests/src/take.spec.ts index 83a3828c7..aa7bd0c34 100644 --- a/packages/algorithm/tests/src/take.spec.ts +++ b/packages/algorithm/tests/src/take.spec.ts @@ -20,13 +20,18 @@ describe('@lumino/algorithm', () => { describe('take() from an iterable iterator', () => { testIterator(() => { - return [take([0, 1, 2, 3][Symbol.iterator](), 1), [0]]; + return [take([0, 1, 2, 3], 1), [0]]; }); }); describe('take() with count=0', () => { - testIterator(() => { - return [take([0, 1, 2, 3][Symbol.iterator](), 0), []]; - }); + testIterator(() => [take([0, 1, 2, 3], 0), []]); + }); + + describe('take() only takes as many as count or are left', () => { + const it = [0, 1, 2, 3, 4, 5, 6][Symbol.iterator](); + testIterator(() => [take(it, 2), [0, 1]]); + testIterator(() => [take(it, 4), [2, 3, 4, 5]]); + testIterator(() => [take(it, 25), [6]]); }); }); From 071756a16daadb67fcde3501d63e7ae52063ad31 Mon Sep 17 00:00:00 2001 From: "Afshin T. Darian" Date: Tue, 16 Aug 2022 20:47:52 +0100 Subject: [PATCH 60/62] Fix typo --- packages/algorithm/src/iter.ts | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/packages/algorithm/src/iter.ts b/packages/algorithm/src/iter.ts index c25f3fce0..8875f32a3 100644 --- a/packages/algorithm/src/iter.ts +++ b/packages/algorithm/src/iter.ts @@ -21,9 +21,7 @@ * ```typescript * import { iter, toArray } from '@lumino/algorithm'; * - * let data = [1, 2, 3, 4, 5, 6]; - * - * let stream = iter(data); + * let stream = [1, 2, 3, 4, 5, 6][Symbol.iterator](); * * toArray(stream); // [1, 2, 3, 4, 5, 6]; * ``` From 1197d7611d0fec2619c1bed1bf8e940f8e11b35d Mon Sep 17 00:00:00 2001 From: "Afshin T. Darian" Date: Tue, 16 Aug 2022 23:18:26 +0100 Subject: [PATCH 61/62] Another .forEach() => for...of --- packages/algorithm/src/sort.ts | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/packages/algorithm/src/sort.ts b/packages/algorithm/src/sort.ts index abf2f7669..08233926b 100644 --- a/packages/algorithm/src/sort.ts +++ b/packages/algorithm/src/sort.ts @@ -72,7 +72,9 @@ export function topologicSort(edges: Iterable<[T, T]>): T[] { visited.add(node); let children = graph.get(node); if (children) { - children.forEach(visit); + for (const child of children) { + visit(child); + } } sorted.push(node); } From c340bd674c0eeea64dbc09b078128cec5283f22b Mon Sep 17 00:00:00 2001 From: Afshin Taylor Darian Date: Wed, 17 Aug 2022 12:01:56 +0100 Subject: [PATCH 62/62] Update packages/algorithm/src/iter.ts Co-authored-by: Vidar Tonaas Fauske --- packages/algorithm/src/iter.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/algorithm/src/iter.ts b/packages/algorithm/src/iter.ts index 8875f32a3..6fd6cdd80 100644 --- a/packages/algorithm/src/iter.ts +++ b/packages/algorithm/src/iter.ts @@ -19,7 +19,7 @@ * * #### Example * ```typescript - * import { iter, toArray } from '@lumino/algorithm'; + * import { toArray } from '@lumino/algorithm'; * * let stream = [1, 2, 3, 4, 5, 6][Symbol.iterator](); *