Normative: add Iterator.zip and Iterator.zipKeyed#3802
Conversation
|
The rendered spec preview for this PR is available as a single page at https://tc39.es/ecma262/pr/3802 and as multiple pages at https://tc39.es/ecma262/pr/3802/multipage . |
e242a5a to
2d41fb7
Compare
| 1. If _mode_ is *"longest"*, then | ||
| 1. Set _paddingOption_ to ? Get(_options_, *"padding"*). |
There was a problem hiding this comment.
It's a bit odd to read padding only when mode is "longest" (rather than unconditionally), but it was present from the start and is covered in test262. I'm not objecting, but do want to draw attention to this behavior.
| 1. Let _iterCount_ be the number of elements in _iters_. | ||
| 1. If _mode_ is *"longest"*, then | ||
| 1. If _paddingOption_ is *undefined*, then | ||
| 1. Repeat _iterCount_ times: |
There was a problem hiding this comment.
Presumably we're intending to document this form as preferred and expecting ESMeta to add support for it? There's also a more concise approach that wouldn't use it:
1. If _mode_ is *"longest"*, then
1. Let _remainingPaddingCount_ be _iterCount_.
1. If _paddingOption_ is not *undefined*, then
1. Let _paddingIter_ be Completion(GetIterator(_paddingOption_, ~sync~)).
1. IfAbruptCloseIterators(_paddingIter_, _iters_).
1. Let _usingIterator_ be *true*.
1. Repeat, while _usingIterator_ is *true* and _remainingPaddingCount_ > 0,
1. Set _next_ to Completion(IteratorStepValue(_paddingIter_)).
1. IfAbruptCloseIterators(_next_, _iters_).
1. If _next_ is ~done~, then
1. Set _usingIterator_ to *false*.
1. Else,
1. Append _next_ to _padding_.
1. Set _remainingPaddingCount_ to _remainingPaddingCount_ - 1.
1. If _usingIterator_ is *true*, then
1. Let _completion_ be Completion(IteratorClose(_paddingIter_, NormalCompletion(~unused~))).
1. IfAbruptCloseIterators(_completion_, _iters_).
1. Repeat, while _remainingPaddingCount_ > 0,
1. Append *undefined* to _padding_.
1. Set _remainingPaddingCount_ to _remainingPaddingCount_ - 1.
| 1. If _iterables_ is not an Object, throw a *TypeError* exception. | ||
| 1. Set _options_ to ? GetOptionsObject(_options_). | ||
| 1. Let _mode_ be ? Get(_options_, *"mode"*). | ||
| 1. If _mode_ is *undefined*, set _mode_ to *"shortest"*. | ||
| 1. If _mode_ is not one of *"shortest"*, *"longest"*, or *"strict"*, throw a *TypeError* exception. | ||
| 1. Let _paddingOption_ be *undefined*. | ||
| 1. If _mode_ is *"longest"*, then | ||
| 1. Set _paddingOption_ to ? Get(_options_, *"padding"*). | ||
| 1. If _paddingOption_ is not *undefined* and _paddingOption_ is not an Object, throw a *TypeError* exception. |
There was a problem hiding this comment.
This is identical to the start of Iterator.zip and it might be worth highlighting that.
| 1. If _iterables_ is not an Object, throw a *TypeError* exception. | |
| 1. Set _options_ to ? GetOptionsObject(_options_). | |
| 1. Let _mode_ be ? Get(_options_, *"mode"*). | |
| 1. If _mode_ is *undefined*, set _mode_ to *"shortest"*. | |
| 1. If _mode_ is not one of *"shortest"*, *"longest"*, or *"strict"*, throw a *TypeError* exception. | |
| 1. Let _paddingOption_ be *undefined*. | |
| 1. If _mode_ is *"longest"*, then | |
| 1. Set _paddingOption_ to ? Get(_options_, *"padding"*). | |
| 1. If _paddingOption_ is not *undefined* and _paddingOption_ is not an Object, throw a *TypeError* exception. | |
| 1. If _iterables_ is not an Object, throw a *TypeError* exception. | |
| 1. Let _resolvedOptions_ be ? ResolveIteratorZipOptions(_options_). | |
| 1. Let _mode_ be _resolvedOptions_.[[Mode]]. | |
| 1. Let _paddingOption_ be _resolvedOptions_.[[Padding]]. |
| 1. If _completion_ is an abrupt completion, then | ||
| 1. Return ? IteratorCloseAll(_openIters_, _completion_). |
There was a problem hiding this comment.
This step can be simplified (because it doesn't mutate openIters):
| 1. If _completion_ is an abrupt completion, then | |
| 1. Return ? IteratorCloseAll(_openIters_, _completion_). | |
| 1. IfAbruptCloseIterators(_completion_, _openIters_). |
It would be great if the steps that do mutate openIters could also be simplified, and I'm wondering how we might do that... maybe by extending IfAbruptCloseIterators with an optional parameter for an element to remove before invoking IteratorCloseAll?
- 1. If _result_ is an abrupt completion, then
- 1. Remove _iter_ from _openIters_.
- 1. Return ? IteratorCloseAll(_openIters_, _result_).
- 1. Set _result_ to ! _result_.
+ 1. IfAbruptCloseIterators(_result_, _openIters_, _iter_).- 1. If _open_ is an abrupt completion, then
- 1. Remove _iters_[_k_] from _openIters_.
- 1. Return ? IteratorCloseAll(_openIters_, _open_).
- 1. Set _open_ to ! _open_.
+ 1. IfAbruptCloseIterators(_open_, _openIters_, _iters_[_k_]).
Pending Stage 4 for https://github.com/tc39/proposal-joint-iteration. Fixes tc39/proposal-joint-iteration#48.