Skip to content

Commit aa794fc

Browse files
committed
Add iterator utility to create a fluent iterator interface
1 parent 4c88642 commit aa794fc

File tree

6 files changed

+811
-0
lines changed

6 files changed

+811
-0
lines changed
Lines changed: 262 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,262 @@
1+
<!--
2+
3+
@license Apache-2.0
4+
5+
Copyright (c) 2019 The Stdlib Authors.
6+
7+
Licensed under the Apache License, Version 2.0 (the "License");
8+
you may not use this file except in compliance with the License.
9+
You may obtain a copy of the License at
10+
11+
http://www.apache.org/licenses/LICENSE-2.0
12+
13+
Unless required by applicable law or agreed to in writing, software
14+
distributed under the License is distributed on an "AS IS" BASIS,
15+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16+
See the License for the specific language governing permissions and
17+
limitations under the License.
18+
19+
-->
20+
21+
# iterFlow
22+
23+
> Create a fluent interface for chaining together [iterator][mdn-iterator-protocol] methods.
24+
25+
<!-- Section to include introductory text. Make sure to keep an empty line after the intro `section` element and another before the `/section` close. -->
26+
27+
<section class="intro">
28+
29+
</section>
30+
31+
<!-- /.intro -->
32+
33+
<!-- Package usage documentation. -->
34+
35+
<section class="usage">
36+
37+
## Usage
38+
39+
```javascript
40+
var iterFlow = require( '@stdlib/iter/flow' );
41+
```
42+
43+
#### iterFlow( methods )
44+
45+
Returns a fluent interface constructor with a customized `prototype` based on provided `methods`.
46+
47+
```javascript
48+
var iterHead = require( '@stdlib/iter/head' );
49+
var iterSome = require( '@stdlib/iter/some' );
50+
51+
// Create a mini-fluent interface having just the methods `head` and `some`:
52+
var FluentIterator = iterFlow({
53+
'head': iterHead,
54+
'some': iterSome
55+
});
56+
```
57+
58+
The `methods` argument should be an `object` which maps constructor method names to [iterator][mdn-iterator-protocol] functions. Each [iterator][mdn-iterator-protocol] function should have the following function signature:
59+
60+
```text
61+
function iterFcn( iterator[, ...args] ) {...}
62+
```
63+
64+
where
65+
66+
- **iterator**: an [iterator][mdn-iterator-protocol]
67+
- **...args**: additional [iterator][mdn-iterator-protocol] function arguments
68+
69+
When a fluent interface [iterator][mdn-iterator-protocol] method is invoked, the method invokes the corresponding [iterator][mdn-iterator-protocol] function with an [iterator][mdn-iterator-protocol] and provided method arguments.
70+
71+
If an [iterator][mdn-iterator-protocol] function returns an [iterator][mdn-iterator-protocol], the corresponding fluent interface method returns a **new** fluent interface instance; otherwise, the corresponding fluent interface method returns the [iterator][mdn-iterator-protocol] function result.
72+
73+
* * *
74+
75+
##### FluentIterator( iterator )
76+
77+
Returns a new fluent interface [iterator][mdn-iterator-protocol] from a source [`iterator`][mdn-iterator-protocol].
78+
79+
```javascript
80+
var array2iterator = require( '@stdlib/array/to-iterator' );
81+
var iterHead = require( '@stdlib/iter/head' );
82+
var iterSome = require( '@stdlib/iter/some' );
83+
84+
// Create a mini-fluent interface having just the methods `head` and `some`:
85+
var FluentIterator = iterFlow({
86+
'head': iterHead,
87+
'some': iterSome
88+
});
89+
90+
// Create a source iterator:
91+
var src = array2iterator( [ 0, 0, 1, 1, 1, 0, 0, 1, 0, 1 ] );
92+
93+
// Convert the source iterator to a fluent interface iterator:
94+
var it = new FluentIterator( src );
95+
96+
// Test if at least 3 of the first 5 iterated values are truthy:
97+
var bool = it.head( 5 ).some( 3 );
98+
// returns true
99+
```
100+
101+
##### FluentIterator.prototype.next()
102+
103+
Returns an [iterator][mdn-iterator-protocol] protocol-compliant object containing the next iterated value (if one exists) assigned to a `value` property and a `done` property having a `boolean` value indicating whether the [iterator][mdn-iterator-protocol] is finished.
104+
105+
```javascript
106+
var array2iterator = require( '@stdlib/array/to-iterator' );
107+
var iterHead = require( '@stdlib/iter/head' );
108+
var iterSome = require( '@stdlib/iter/some' );
109+
110+
// Create a mini-fluent interface having just the methods `head` and `some`:
111+
var FluentIterator = iterFlow({
112+
'head': iterHead,
113+
'some': iterSome
114+
});
115+
116+
// Create a source iterator:
117+
var src = array2iterator( [ 0, 0, 1, 1, 1, 0, 0, 1, 0, 1 ] );
118+
119+
// Create a fluent interface iterator:
120+
var it1 = new FluentIterator( src );
121+
122+
// Invoke the `head` method to return an iterator limited to the first 5 source values:
123+
var it2 = it1.head( 5 );
124+
125+
// Perform manual iteration...
126+
var v;
127+
while ( true ) {
128+
v = it2.next();
129+
if ( v.done ) {
130+
break;
131+
}
132+
console.log( v.value );
133+
}
134+
```
135+
136+
##### FluentIterator.prototype.return( \[value] )
137+
138+
Closes a fluent interface [iterator][mdn-iterator-protocol] and returns a single (optional) argument in an [iterator][mdn-iterator-protocol] protocol-compliant object.
139+
140+
```javascript
141+
var array2iterator = require( '@stdlib/array/to-iterator' );
142+
var iterHead = require( '@stdlib/iter/head' );
143+
var iterSome = require( '@stdlib/iter/some' );
144+
145+
// Create a mini-fluent interface having just the methods `head` and `some`:
146+
var FluentIterator = iterFlow({
147+
'head': iterHead,
148+
'some': iterSome
149+
});
150+
151+
// Create a source iterator:
152+
var src = array2iterator( [ 0, 0, 1, 1, 1, 0, 0, 1, 0, 1 ] );
153+
154+
// Create a fluent interface iterator:
155+
var it1 = new FluentIterator( src );
156+
157+
// Invoke the `head` method to return an iterator limited to the first 5 source values:
158+
var it2 = it1.head( 5 );
159+
160+
// Get the first value:
161+
var v = it2.next().value;
162+
// returns 0
163+
164+
// Get the second value:
165+
v = it2.next().value;
166+
// returns 0
167+
168+
// Get the third value:
169+
v = it2.next().value;
170+
// returns 1
171+
172+
// Close the iterator:
173+
var bool = it2.return().done;
174+
// returns true
175+
176+
// Attempt to get the fourth value:
177+
v = it2.next().value;
178+
// returns undefined
179+
```
180+
181+
</section>
182+
183+
<!-- /.usage -->
184+
185+
<!-- Package usage notes. Make sure to keep an empty line after the `section` element and another before the `/section` close. -->
186+
187+
* * *
188+
189+
<section class="notes">
190+
191+
## Notes
192+
193+
- The [iterator][mdn-iterator-protocol] function evaluation context is **always** `null`.
194+
- [Iterator][mdn-iterator-protocol] functions which return [iterators][mdn-iterator-protocol] are **expected** to return [iterator][mdn-iterator-protocol] protocol-compliant objects (i.e., an `object` having a `next` method which returns the next iterated value (if one exists) assigned to a `value` property and a `done` property having a `boolean` value indicating whether the [iterator][mdn-iterator-protocol] is finished).
195+
- If an environment supports `Symbol.iterator`, the returned iterator is iterable.
196+
197+
</section>
198+
199+
<!-- /.notes -->
200+
201+
<!-- Package usage examples. -->
202+
203+
* * *
204+
205+
<section class="examples">
206+
207+
## Examples
208+
209+
<!-- eslint no-undef: "error" -->
210+
211+
```javascript
212+
var array2iterator = require( '@stdlib/array/to-iterator' );
213+
var iterHead = require( '@stdlib/iter/head' );
214+
var iterSome = require( '@stdlib/iter/some' );
215+
var iterFlow = require( '@stdlib/iter/flow' );
216+
217+
// Create a "fluent" interface:
218+
var FluentIterator = iterFlow({
219+
'head': iterHead,
220+
'some': iterSome
221+
});
222+
223+
// Create a source iterator:
224+
var arr = array2iterator( [ 0, 0, 1, 1, 1, 0, 0, 1, 0, 1 ] );
225+
226+
// Create a new iterator:
227+
var it = new FluentIterator( arr );
228+
229+
var bool = it.head( 5 ).some( 3 );
230+
// returns true
231+
232+
// Create another source iterator:
233+
arr = array2iterator( [ 0, 0, 1, 0, 1, 0, 0, 1, 0, 1 ] );
234+
235+
// Create a new iterator:
236+
it = new FluentIterator( arr );
237+
238+
bool = it.head( 5 ).some( 3 );
239+
// returns false
240+
```
241+
242+
</section>
243+
244+
<!-- /.examples -->
245+
246+
<!-- Section to include cited references. If references are included, add a horizontal rule *before* the section. Make sure to keep an empty line after the `section` element and another before the `/section` close. -->
247+
248+
<section class="references">
249+
250+
</section>
251+
252+
<!-- /.references -->
253+
254+
<!-- Section for all links. Make sure to keep an empty line after the `section` element and another before the `/section` close. -->
255+
256+
<section class="links">
257+
258+
[mdn-iterator-protocol]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Iteration_protocols#The_iterator_protocol
259+
260+
</section>
261+
262+
<!-- /.links -->

0 commit comments

Comments
 (0)