Skip to content

Commit 9663042

Browse files
committed
Add utility to invoke a function a specified number of times
1 parent bcc5431 commit 9663042

8 files changed

Lines changed: 539 additions & 0 deletions

File tree

Lines changed: 109 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,109 @@
1+
# mapFun
2+
3+
> Invoke a function `n` times and return an array of accumulated function return values.
4+
5+
6+
<!-- Section to include introductory text. Make sure to keep an empty line after the intro `section` element and another before the `/section` close. -->
7+
8+
<section class="intro">
9+
10+
</section>
11+
12+
<!-- /.intro -->
13+
14+
<!-- Package usage documentation. -->
15+
16+
<section class="usage">
17+
18+
## Usage
19+
20+
``` javascript
21+
var mapFun = require( '@stdlib/utils/map-function' );
22+
```
23+
24+
#### mapFun( fcn, n\[, thisArg \] )
25+
26+
Invokes a function `n` times and returns an `array` of accumulated function return values.
27+
28+
``` javascript
29+
function fcn( i ) {
30+
return i;
31+
}
32+
33+
var arr = mapFun( fcn, 5 );
34+
// returns [ 0, 1, 2, 3, 4 ]
35+
```
36+
37+
To set the function execution context, provide a `thisArg`.
38+
39+
``` javascript
40+
function fcn( i ) {
41+
this.count += 1;
42+
return i;
43+
}
44+
45+
var context = {
46+
'count': 0
47+
};
48+
49+
var arr = mapFun( fcn, 5, context );
50+
// returns [ 0, 1, 2, 3, 4 ]
51+
52+
console.log( context.count );
53+
// => 5
54+
```
55+
56+
57+
</section>
58+
59+
<!-- /.usage -->
60+
61+
<!-- Package usage notes. Make sure to keep an empty line after the `section` element and another before the `/section` close. -->
62+
63+
<section class="notes">
64+
65+
## Notes
66+
67+
* The invoked `function` is provided a single argument: the invocation index (zero-based).
68+
69+
</section>
70+
71+
<!-- /.notes -->
72+
73+
<!-- Package usage examples. -->
74+
75+
<section class="examples">
76+
77+
## Examples
78+
79+
``` javascript
80+
var randu = require( '@stdlib/math/base/random/randu' );
81+
var mapFun = require( '@stdlib/utils/map-function' );
82+
83+
function rand( i ) {
84+
return randu() * i * 10.0;
85+
}
86+
87+
var arr = mapFun( rand, 100 );
88+
console.log( arr );
89+
```
90+
91+
</section>
92+
93+
<!-- /.examples -->
94+
95+
<!-- 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. -->
96+
97+
<section class="references">
98+
99+
</section>
100+
101+
<!-- /.references -->
102+
103+
<!-- Section for all links. Make sure to keep an empty line after the `section` element and another before the `/section` close. -->
104+
105+
<section class="links">
106+
107+
</section>
108+
109+
<!-- /.links -->
Lines changed: 134 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,134 @@
1+
'use strict';
2+
3+
// MODULES //
4+
5+
var bench = require( '@stdlib/bench' );
6+
var isArray = require( '@stdlib/assert/is-array' );
7+
var pkg = require( './../package.json' ).name;
8+
var mapFun = require( './../lib' );
9+
10+
11+
// MAIN //
12+
13+
bench( pkg, function benchmark( b ) {
14+
var o;
15+
var i;
16+
17+
function fcn( i ) {
18+
return i;
19+
}
20+
21+
b.tic();
22+
for ( i = 0; i < b.iterations; i++ ) {
23+
o = mapFun( fcn, 100 );
24+
if ( o.length === 0 ) {
25+
b.fail( 'should return an output array' );
26+
}
27+
}
28+
b.toc();
29+
if ( !isArray( o ) ) {
30+
b.fail( 'should return an output array' );
31+
}
32+
b.pass( 'benchmark finished' );
33+
b.end();
34+
});
35+
36+
bench( pkg+'::loop,function', function benchmark( b ) {
37+
var arr;
38+
var i;
39+
var j;
40+
41+
function fcn( i ) {
42+
return i;
43+
}
44+
45+
b.tic();
46+
for ( i = 0; i < b.iterations; i++ ) {
47+
arr = [];
48+
for ( j = 0; j < 100; j++ ) {
49+
arr.push( fcn( j ) );
50+
}
51+
if ( arr.length === 0 ) {
52+
b.fail( 'should not be empty' );
53+
}
54+
}
55+
b.toc();
56+
if ( arr.length === 0 ) {
57+
b.fail( 'should not be empty' );
58+
}
59+
b.pass( 'benchmark finished' );
60+
b.end();
61+
});
62+
63+
bench( pkg+'::loop,function_call', function benchmark( b ) {
64+
var arr;
65+
var i;
66+
var j;
67+
68+
function fcn( i ) {
69+
return i;
70+
}
71+
72+
b.tic();
73+
for ( i = 0; i < b.iterations; i++ ) {
74+
arr = [];
75+
for ( j = 0; j < 100; j++ ) {
76+
arr.push( fcn.call( {}, j ) );
77+
}
78+
if ( arr.length === 0 ) {
79+
b.fail( 'should not be empty' );
80+
}
81+
}
82+
b.toc();
83+
if ( arr.length === 0 ) {
84+
b.fail( 'should not be empty' );
85+
}
86+
b.pass( 'benchmark finished' );
87+
b.end();
88+
});
89+
90+
bench( pkg+'::loop', function benchmark( b ) {
91+
var arr;
92+
var i;
93+
var j;
94+
95+
b.tic();
96+
for ( i = 0; i < b.iterations; i++ ) {
97+
arr = [];
98+
for ( j = 0; j < 100; j++ ) {
99+
arr.push( j );
100+
}
101+
if ( arr.length === 0 ) {
102+
b.fail( 'should not be empty' );
103+
}
104+
}
105+
b.toc();
106+
if ( arr.length === 0 ) {
107+
b.fail( 'should not be empty' );
108+
}
109+
b.pass( 'benchmark finished' );
110+
b.end();
111+
});
112+
113+
bench( pkg+'::this_context', function benchmark( b ) {
114+
var o;
115+
var i;
116+
117+
function fcn( i ) {
118+
return i;
119+
}
120+
121+
b.tic();
122+
for ( i = 0; i < b.iterations; i++ ) {
123+
o = mapFun( fcn, 100, {} );
124+
if ( o.length === 0 ) {
125+
b.fail( 'should return an output array' );
126+
}
127+
}
128+
b.toc();
129+
if ( !isArray( o ) ) {
130+
b.fail( 'should return an output array' );
131+
}
132+
b.pass( 'benchmark finished' );
133+
b.end();
134+
});
Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
2+
{{alias}}( fcn, n[, thisArg] )
3+
Invokes a function `n` times and returns an array of accumulated function
4+
return values.
5+
6+
The invoked function is provided a single argument: the invocation index
7+
(zero-based).
8+
9+
Parameters
10+
----------
11+
fcn: Function
12+
Function to invoke.
13+
14+
n: integer
15+
Number of times to invoke a function.
16+
17+
thisArg: any (optional)
18+
Function execution context.
19+
20+
Returns
21+
-------
22+
out: Array
23+
Array of accumulated function return values.
24+
25+
Examples
26+
--------
27+
> function fcn( i ) { return i; };
28+
> var arr = mapFun( fcn, 5 )
29+
[ 0, 1, 2, 3, 4 ]
30+
31+
See Also
32+
--------
33+
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
'use strict';
2+
3+
var randu = require( '@stdlib/math/base/random/randu' );
4+
var mapFun = require( './../lib' );
5+
6+
function rand( i ) {
7+
return randu() * i * 10.0;
8+
}
9+
10+
var arr = mapFun( rand, 100 );
11+
console.log( arr );
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
'use strict';
2+
3+
/**
4+
* Invoke a function `n` times and return an array of accumulated function return values.
5+
*
6+
* @module @stdlib/utils/map-function
7+
*
8+
* @example
9+
* var mapFun = require( '@stdlib/utils/map-function' );
10+
*
11+
* function fcn( i ) {
12+
* return i;
13+
* }
14+
*
15+
* var arr = mapFun( fcn, 5 );
16+
* // returns [ 0, 1, 2, 3, 4 ]
17+
*/
18+
19+
// MODULES //
20+
21+
var mapFun = require( './map_function.js' );
22+
23+
24+
// EXPORTS //
25+
26+
module.exports = mapFun;
Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
'use strict';
2+
3+
// MODULES //
4+
5+
var isFunction = require( '@stdlib/assert/is-function' );
6+
var isNonNegativeInteger = require( '@stdlib/assert/is-nonnegative-integer' ).isPrimitive;
7+
8+
9+
// MAIN //
10+
11+
/**
12+
* Invokes a function `n` times and returns an array of accumulated function return values.
13+
*
14+
* @param {Function} fcn - function to invoke
15+
* @param {NonNegativeInteger} n - number of function invocations
16+
* @param {*} [thisArg] - execution context
17+
* @throws {TypeError} first argument must be a function
18+
* @throws {TypeError} second argument must be a nonnegative integer
19+
* @returns {Array} accumulated results
20+
*
21+
* @example
22+
* function fcn( i ) {
23+
* return i;
24+
* }
25+
*
26+
* var arr = mapFun( fcn, 5 );
27+
* // returns [ 0, 1, 2, 3, 4 ]
28+
*/
29+
function mapFun( fcn, n, thisArg ) {
30+
var out;
31+
var i;
32+
if ( !isFunction( fcn ) ) {
33+
throw new TypeError( 'invalid input argument. First argument must be a function. Value: `'+fcn+'`.' );
34+
}
35+
if ( !isNonNegativeInteger( n ) ) {
36+
throw new TypeError( 'invalid input argument. Second argument must be a nonnegative integer. Value: `'+n+'`.' );
37+
}
38+
// Note: we explicitly do not preallocate in order to ensure "fast" elements for large output arrays (i.e., >64K elements).
39+
out = [];
40+
for ( i = 0; i < n; i++ ) {
41+
out.push( fcn.call( thisArg, i ) );
42+
}
43+
return out;
44+
} // end FUNCTION mapFun()
45+
46+
47+
// EXPORTS //
48+
49+
module.exports = mapFun;

0 commit comments

Comments
 (0)