main.js (3574B)
1 /** 2 * @license Apache-2.0 3 * 4 * Copyright (c) 2019 The Stdlib Authors. 5 * 6 * Licensed under the Apache License, Version 2.0 (the "License"); 7 * you may not use this file except in compliance with the License. 8 * You may obtain a copy of the License at 9 * 10 * http://www.apache.org/licenses/LICENSE-2.0 11 * 12 * Unless required by applicable law or agreed to in writing, software 13 * distributed under the License is distributed on an "AS IS" BASIS, 14 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 * See the License for the specific language governing permissions and 16 * limitations under the License. 17 */ 18 19 'use strict'; 20 21 // MODULES // 22 23 var setReadOnly = require( '@stdlib/utils/define-nonenumerable-read-only-property' ); 24 var isIteratorLike = require( '@stdlib/assert/is-iterator-like' ); 25 var isPositiveInteger = require( '@stdlib/assert/is-positive-integer' ).isPrimitive; 26 var isFunction = require( '@stdlib/assert/is-function' ); 27 var hasOwnProp = require( '@stdlib/assert/has-own-property' ); 28 var iteratorSymbol = require( '@stdlib/symbol/iterator' ); 29 var incrmrange = require( './../../../incr/mrange' ); 30 31 32 // MAIN // 33 34 /** 35 * Returns an iterator which iteratively computes a moving range. 36 * 37 * @param {Iterator} iterator - input iterator 38 * @param {PositiveInteger} W - window size 39 * @throws {TypeError} first argument must be an iterator 40 * @throws {TypeError} second argument must be a positive integer 41 * @returns {Iterator} iterator 42 * 43 * @example 44 * var runif = require( '@stdlib/random/iter/uniform' ); 45 * 46 * var rand = runif( -10.0, 10.0, { 47 * 'iter': 100 48 * }); 49 * 50 * var it = itermrange( rand, 3 ); 51 * 52 * var v = it.next().value; 53 * // returns <number> 54 * 55 * v = it.next().value; 56 * // returns <number> 57 * 58 * v = it.next().value; 59 * // returns <number> 60 * 61 * // ... 62 */ 63 function itermrange( iterator, W ) { 64 var iter; 65 var FLG; 66 var acc; 67 if ( !isIteratorLike( iterator ) ) { 68 throw new TypeError( 'invalid argument. First argument must be an iterator. Value: `' + iterator + '`.' ); 69 } 70 if ( !isPositiveInteger( W ) ) { 71 throw new TypeError( 'invalid argument. Second argument must be a positive integer. Value: `' + W + '`.' ); 72 } 73 acc = incrmrange( W ); 74 75 // Create an iterator protocol-compliant object: 76 iter = {}; 77 setReadOnly( iter, 'next', next ); 78 setReadOnly( iter, 'return', end ); 79 80 // If an environment supports `Symbol.iterator`, make the iterator iterable: 81 if ( iteratorSymbol && isFunction( iterator[ iteratorSymbol ] ) ) { 82 setReadOnly( iter, iteratorSymbol, factory ); 83 } 84 return iter; 85 86 /** 87 * Returns an iterator protocol-compliant object containing the next iterated value. 88 * 89 * @private 90 * @returns {Object} iterator protocol-compliant object 91 */ 92 function next() { 93 var out; 94 var v; 95 if ( FLG ) { 96 return { 97 'done': true 98 }; 99 } 100 out = {}; 101 v = iterator.next(); 102 if ( typeof v.value === 'number' ) { 103 out.value = acc( v.value ); 104 } else if ( hasOwnProp( v, 'value' ) ) { 105 out.value = acc( NaN ); 106 } 107 if ( v.done ) { 108 FLG = true; 109 out.done = true; 110 } else { 111 out.done = false; 112 } 113 return out; 114 } 115 116 /** 117 * Finishes an iterator. 118 * 119 * @private 120 * @param {*} [value] - value to return 121 * @returns {Object} iterator protocol-compliant object 122 */ 123 function end( value ) { 124 FLG = true; 125 if ( arguments.length ) { 126 return { 127 'value': value, 128 'done': true 129 }; 130 } 131 return { 132 'done': true 133 }; 134 } 135 136 /** 137 * Returns a new iterator. 138 * 139 * @private 140 * @returns {Iterator} iterator 141 */ 142 function factory() { 143 return itermrange( iterator[ iteratorSymbol ](), W ); 144 } 145 } 146 147 148 // EXPORTS // 149 150 module.exports = itermrange;