-
-
Notifications
You must be signed in to change notification settings - Fork 127
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Use native iterators instead of Lumino iterators #346
Conversation
349ac0c
to
8c3b2c0
Compare
cc: @jasongrout @vidartf @ibdafna @mwcraig — apropos our conversation about Lumino 2's impact on |
89f9a77
to
0da98e4
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nice work, thank you!
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
thanks a lot for this @afshin
Would you mind adding a migration.rst
file in the documentation that include your very useful advices from the this PR description.
I added |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Good work here! I tried my best to review the code in the actual algorithm package vs behavior changes, and made some comments w.r.t that. Also added some nitpicks since I was already looking 😄
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 toArray
and toObject
functions 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 || ^2
dependency.
Because the types have changed, even a convenience |
547d400
to
b0227e8
Compare
If I have code |
If your
|
Right - I thought what @vidartf was proposing was deprecated functions that allowed you to do |
8cb47a7
to
84ec11b
Compare
…placeholder for Array.from()
@vidartf, @jasongrout, @davidbrochart, two things:
|
ab4ec58
to
c6673e8
Compare
Co-authored-by: Vidar Tonaas Fauske <[email protected]>
Let's merge and...iterate. |
This PR refactors Lumino packages to switch to iterators and generators (Mozilla (MDN), TypeScript) instead of custom Lumino iterators. Fixes #333.
Iteration suggestions for Lumino users
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 in Lumino 2.
Use
each(...)
sparinglyIterating through an iterable
bar: Iterable<T>
using nativefor...of
, e.g.,for (const foo of bar) {...}
is almost always a better option than usingeach(bar, foo => ...)
. Some exceptions to this are:.forEach(...)
.forEach(...)
method but you want to be able to terminate iteration early, which you cannot do natively, but can witheach(...)
by returningfalse
Nearly all invocations of
each(...)
have been removed in Lumino 2 (except for tests). See, for example, this commit.Use
[].forEach(...)
sparinglyNow that we support native ES6 iteration,
for (const value of someArray) {...}
should be favored oversomeArray.forEach(...)
because it will not require a context shift every time it invokes the function being applied.Use
[Symbol.iterator]()
sparinglyUnless 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 implementreduce(...)
in Lumino 2), most of the time you can simply usefor...of
to iterate through any object that has aSymbol.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 newSymbol.iterator
method.Use
Array.from(...)
sparinglytoArray(...)
has been deprecated. You may be tempted to swap inArray.from(...)
when you update your code. This will work, but if you simply need to iterate through an iterable, you can usefor...of
directly on the iterable object. This is more performant both in terms of CPU and memory than allocating and populating newArray
instance before iteration.If you need a snapshot of every item in your iterable as an array, then
Array.from(...)
is an appropriate replacement fortoArray(...)
.Public API changes
@lumino/algorithm
All of the iterator utilities have been changed to use native generators and iterators.
export
type
IterableOrArrayLike<T>
Iterable<T>
interface
IIterable<T>
Iterable<T>
interface
IIterator<T>
Iterator<T>
/IterableIterator<T>
function
iter<T>(...)
Symbol.iterator
andfunction*
function
iterFn<T>(...)
function*
function
iterItems<T>(...)
function
iterKeys<T>(...)
for ... in
function
iterValues<T>(...)
for ... of
class
ArrayIterator<T>
[][Symbol.iterator]()
class
ChainIterator<T>
chain<T>()
class
EmptyIterator<T>
empty<T>()
class
EnumerateIterator<T>
enumerate<T>()
class
FilterIterator<T>
filter<T>()
class
FnIterator<T>
class
ItemIterator<T>
class
KeyIterator
for ... in
class
MapIterator<T>
map<T>()
class
RangeIterator<T>
range()
class
RetroIterator<T>
retro<T>()
class
StrideIterator<T>
stride<T>()
class
TakeIterator<T>
take<T>()
class
ValueIterator<T>
for ... of
class
ZipIterator<T>
zip<T>()
function
chain<T>(...)
function
each<T>(...)
function
empty<T>(...)
function
enumerate<T>(...)
function
every<T>(...)
function
filter<T>(...)
function
find<T>(...)
function
findIndex<T>(...)
function
map<T>(...)
function
max<T>(...)
function
min<T>(...)
function
minmax<T>(...)
function
reduce<T>(...)
function
range(...)
function
retro<T>(...)
function
some<T>(...)
function
stride<T>(...)
function
take<T>(...)
function
toArray<T>(...)
@deprecated
, useArray.from(...)
orfor ... of
function
toObject(...)
function
topologicSort<T>(...)
function
zip<T>(...)
@lumino/collections
LinkedList
has been updated to accept native iterables and return native iterators.export
class
LinkedList.ForwardValueIterator
LinkedList#[Symbol.iterator]
class
LinkedList.RetroValueIterator
LinkedList#retro()
class
LinkedList.ForwardNodeIterator
LinkedList#nodes()
class
LinkedList.RetroNodeIterator
LinkedList#retroNodes()
method
LinkedList#iter()
LinkedList#[Symbol.iterator]
function
LinkedList.from<T>(...)
Iterable<T>
method
LinkedList#assign(...)
Iterable<T>
method
LinkedList#nodes()
IterableIterator<LinkedList.INode<T>>
method
LinkedList#retro()
IterableIterator<T>
method
LinkedList#retroNodes()
IterableIterator<LinkedList.INode<T>>
@lumino/datagrid
DataGrid
selections are now native iterators.export
method
BasicSelectionModel#selections()
IterableIterator<SelectionModel.Selection>
method
SelectionModel#selections()
IterableIterator<SelectionModel.Selection>
@lumino/disposable
Helper functions for
DisposableSet
andObservableDisposableSet
have been udpated.export
function
DisposableSet.from(...)
Iterable<IDisposable>
function
ObservableDisposableSet.from(...)
Iterable<IDisposable>
@lumino/widgets
Layout
and its sub-classes now use native iterators, e.g.implements Iterable<Widget>
.export
method
DockLayout#iter()
DockLayout#[Symbol.iterator]
method
GridLayout#iter()
GridLayout#[Symbol.iterator]
method
Layout#iter()
Layout#[Symbol.iterator]
method
PanelLayout#iter()
PanelLayout#[Symbol.iterator]
method
SingletonLayout#iter()
SingletonLayout#[Symbol.iterator]
method
DockLayout#handles()
IterableIterator<HTMLDivElement>
method
DockLayout#selectedWidgets()
IterableIterator<Widget>
method
DockLayout#tabBars()
IterableIterator<TabBar<Widget>>
method
DockLayout#widgets()
IterableIterator<Widget>
method
DockPanel#handles()
IterableIterator<HTMLDivElement>
method
DockPanel#selectedWidgets()
IterableIterator<Widget>
method
DockPanel#tabBars()
IterableIterator<TabBar<Widget>>
method
DockPanel#widgets()
IterableIterator<Widget>
method
Widget#children()
IterableIterator<Widget>