lumino
lumino copied to clipboard
Use native iterators instead of Lumino iterators
This PR refactors Lumino packages to Switch to iterators and generators (Mozilla (MDN), TypeScript) instead of custom Lumino iterators. Fixes #333.
Public API changes
@lumino/algorithm
All of the iterator utilities have been changed to use native generators and iterators.
export |
name | note | |
|---|---|---|---|
| ❌ | type |
IterableOrArrayLike<T> |
Switch to Iterable<T> |
| ❌ | interface |
IIterable<T> |
Switch to Iterable<T> |
| ❌ | interface |
IIterator<T> |
Switch to Iterator<T> / IterableIterator<T> |
| ❌ | function |
iter<T>(...) |
Switch to Symbol.iterator and function* |
| ❌ | function |
iterFn<T>(...) |
Switch to function* |
| ❌ | function |
iterItems<T>(...) |
We aren't using this function anywhere |
| ❌ | function |
iterKeys<T>(...) |
Switch to for ... in |
| ❌ | function |
iterValues<T>(...) |
Switch to for ... of |
| ❌ | function |
toArray<T>(...) |
Switch to Array.from(...) |
| ❌ | function |
toObject(...) |
We aren't using this function anywhere |
| ❌ | class |
ArrayIterator<T> |
Switch to [][Symbol.iterator]() |
| ❌ | class |
ChainIterator<T> |
Previous implementation of chain<T>() |
| ❌ | class |
EmptyIterator<T> |
Previous implementation of empty<T>() |
| ❌ | class |
EnumerateIterator<T> |
Previous implementation of enumerate<T>() |
| ❌ | class |
FilterIterator<T> |
Previous implementation of filter<T>() |
| ❌ | class |
FnIterator<T> |
Switch to generators |
| ❌ | class |
ItemIterator<T> |
We aren't using this class anywhere |
| ❌ | class |
KeyIterator |
Switch to for ... in |
| ❌ | class |
MapIterator<T> |
Previous implementation of map<T>() |
| ❌ | class |
RangeIterator<T> |
Previous implementation of range() |
| ❌ | class |
RetroIterator<T> |
Previous implementation of retro<T>() |
| ❌ | class |
StrideIterator<T> |
Previous implementation of stride<T>() |
| ❌ | class |
TakeIterator<T> |
Previous implementation of take<T>() |
| ❌ | class |
ValueIterator<T> |
Switch to for ... of |
| ❌ | class |
ZipIterator<T> |
Previous implementation of zip<T>() |
| ✅ | function |
chain<T>(...) |
Reimplement with native types |
| ✅ | function |
each<T>(...) |
Reimplement with native types |
| ✅ | function |
empty<T>(...) |
Reimplement with native types |
| ✅ | function |
enumerate<T>(...) |
Reimplement with native types |
| ✅ | function |
every<T>(...) |
Reimplement with native types |
| ✅ | function |
filter<T>(...) |
Reimplement with native types |
| ✅ | function |
find<T>(...) |
Reimplement with native types |
| ✅ | function |
findIndex<T>(...) |
Reimplement with native types |
| ✅ | function |
map<T>(...) |
Reimplement with native types |
| ✅ | function |
max<T>(...) |
Reimplement with native types |
| ✅ | function |
min<T>(...) |
Reimplement with native types |
| ✅ | function |
minmax<T>(...) |
Support native types |
| ✅ | function |
reduce<T>(...) |
Support native types |
| ✅ | function |
range(...) |
Reimplement with native types |
| ✅ | function |
retro<T>(...) |
Reimplement with native types |
| ✅ | function |
some<T>(...) |
Reimplement with native types |
| ✅ | function |
stride<T>(...) |
Reimplement with native types |
| ✅ | function |
take<T>(...) |
Reimplement with native types |
| ✅ | function |
topologicSort<T>(...) |
Support native types |
| ✅ | function |
zip<T>(...) |
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<T>(...) |
Accept Iterable<T> |
| ✅ | method |
LinkedList#assign(...) |
Accept Iterable<T> |
| ✅ | method |
LinkedList#nodes() |
Return IterableIterator<LinkedList.INode<T>> |
| ✅ | method |
LinkedList#retro() |
Return IterableIterator<T> |
| ✅ | method |
LinkedList#retroNodes() |
Return IterableIterator<LinkedList.INode<T>> |
@lumino/datagrid
DataGrid selections are now native iterators.
export |
name | note | |
|---|---|---|---|
| ✅ | method |
BasicSelectionModel#selections() |
Return IterableIterator<SelectionModel.Selection> |
| ✅ | method |
SelectionModel#selections() |
Return IterableIterator<SelectionModel.Selection> |
@lumino/disposable
Helper functions for DisposableSet and ObservableDisposableSet have been udpated.
export |
name | note | |
|---|---|---|---|
| ✅ | function |
DisposableSet.from(...) |
Accept Iterable<IDisposable> |
| ✅ | function |
ObservableDisposableSet.from(...) |
Accept Iterable<IDisposable> |
@lumino/widgets
Layout and its sub-classes now use native iterators, e.g. implements Iterable<Widget>.
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<HTMLDivElement> |
| ✅ | method |
DockLayout#selectedWidgets() |
Return IterableIterator<Widget> |
| ✅ | method |
DockLayout#tabBars() |
Return IterableIterator<TabBar<Widget>> |
| ✅ | method |
DockLayout#widgets() |
Return IterableIterator<Widget> |
| ✅ | method |
DockPanel#handles() |
Return IterableIterator<HTMLDivElement> |
| ✅ | method |
DockPanel#selectedWidgets() |
Return IterableIterator<Widget> |
| ✅ | method |
DockPanel#tabBars() |
Return IterableIterator<TabBar<Widget>> |
| ✅ | method |
DockPanel#widgets() |
Return IterableIterator<Widget> |
| ✅ | method |
Widget#children() |
Return IterableIterator<Widget> |
cc: @jasongrout @vidartf @ibdafna @mwcraig — apropos our conversation about Lumino 2's impact on @jupyter-widgets/* packages on the Jupyter Widgets weekly call.
I added migration.md (because the docs apparently can be .rst or .md) but I'm still not sure the docs are building/working properly. I'd propose leaving that to fix in:
- https://github.com/jupyterlab/lumino/issues/340,
- https://github.com/jupyterlab/lumino/issues/336
As a maintainer of a few library packages dependent on Lumino, my main question for Lumino v2 will be "how hard will it be for my code-base to support both v1 and v2 during the transition period?". The fewer conditionals I need on version or contorted imports that will be needed, the better managed the upgrade will be. In that regards, I think there might be value in keeping the
toArrayandtoObjectfunctions around as deprecated convenience functions. AFAICT, there should be little maintenance cost in keeping them for a cycle, while it should bring high benefit to anyone that wants that^1 || ^2dependency.
Because the types have changed, even a convenience toArray and toObject won't stop you from having to rewrite code. I strongly advocate for removing these, but I'm prepared to be outvoted on this 🙂
Because the types have changed, even a convenience toArray and toObject won't stop you from having to rewrite code. I strongly advocate for removing these, but I'm prepared to be outvoted on this 🙂
If I have code toArray(luminoiterator), how would I need to rewrite code? Before luminoiterator was a lumino iterator, now it is a js iterator, but either way I get an array in the end, without having to change my code, right?
If I have code
toArray(luminoiterator), how would I need to rewrite code? Before luminoiterator was a lumino iterator, now it is a js iterator, but either way I get an array in the end, without having to change my code, right?
If your luminoiterator is now a native iterable by virtue of something upstream having changed its types, then I would have some suggestions for how you should change your code:
- Do you really need for it to be an array? In many cases, you should probably use
for ... of - If you truly need it to be an array, use
Array.from(luminoiterator)(with the understanding thatluminoiteratoris no longer a Lumino iterator)
for how you should change your code:
Right - I thought what @vidartf was proposing was deprecated functions that allowed you to do ^1||^2 without changing code, without too much burden on lumino maintainers (i.e., keep toArray since it is used often). I'm +1 on easing the transition with a deprecation cycle for common functions.
@vidartf, @jasongrout, @davidbrochart, two things:
- I reimplemented
toObject(...)even though we weren't using it because it's pretty straightforward and doesn't hurt. - I re-added
toArraywith a@deprecatedtag.
Let's merge and...iterate.