time-to-botec

Benchmark sampling in different programming languages
Log | Files | Refs | README

README.md (10521B)


      1 <!--
      2 
      3 @license Apache-2.0
      4 
      5 Copyright (c) 2018 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 # inmapRightAsync
     22 
     23 > Invoke a function for each element in a collection and update the collection in-place, iterating from right to left.
     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 inmapRightAsync = require( '@stdlib/utils/async/inmap-right' );
     41 ```
     42 
     43 #### inmapRightAsync( collection, \[options,] fcn, done )
     44 
     45 Invokes a function for each element in a `collection` and updates the `collection` in-place, iterating from right to left.
     46 
     47 <!-- eslint-disable no-use-before-define -->
     48 
     49 ```javascript
     50 function fcn( value, index, next ) {
     51     setTimeout( onTimeout, value );
     52     function onTimeout() {
     53         console.log( value );
     54         next( null, value*index );
     55     }
     56 }
     57 
     58 function done( error, collection ) {
     59     if ( error ) {
     60         throw error;
     61     }
     62     console.log( collection === arr );
     63     console.log( collection );
     64 }
     65 
     66 var arr = [ 1000, 2500, 3000 ];
     67 
     68 inmapRightAsync( arr, fcn, done );
     69 /*
     70     1000
     71     2500
     72     3000
     73     true
     74     [ 0, 2500, 6000 ]
     75 */
     76 ```
     77 
     78 The `next` callback accepts two arguments: `error` and `result`. The second argument to the `next` callback is used to update the `collection` element for the corresponding collection `index`, thus mutating the input `collection`.
     79 
     80 ```javascript
     81 function fcn( value, index, next ) {
     82     setTimeout( onTimeout, value );
     83     function onTimeout() {
     84         next( null, 'beep: '+index );
     85     }
     86 }
     87 
     88 function done( error, collection ) {
     89     if ( error ) {
     90         throw error;
     91     }
     92     console.log( collection );
     93     // => [ 'beep: 0', 'beep: 1', 'beep: 2' ]
     94 }
     95 
     96 var arr = [ 1000, 2500, 3000 ];
     97 
     98 inmapRightAsync( arr, fcn, done );
     99 ```
    100 
    101 If the `next` callback is called with an `error` argument, the input `collection` may be **partially** mutated.
    102 
    103 ```javascript
    104 function fcn( value, index, next ) {
    105     setTimeout( onTimeout, value );
    106     function onTimeout() {
    107         if ( index === 1 ) {
    108             return next( new Error( 'boop' ) );
    109         }
    110         next( null, 'beep: '+index );
    111     }
    112 }
    113 
    114 function done( error, collection ) {
    115     if ( error ) {
    116         // Ignore error...
    117     }
    118     console.log( collection );
    119     // => [ 1000, 2000, 'beep: 2' ]
    120 }
    121 
    122 var arr = [ 1000, 2000, 3000 ];
    123 
    124 inmapRightAsync( arr, fcn, done );
    125 ```
    126 
    127 The function accepts the following `options`:
    128 
    129 -   `limit`: the maximum number of pending invocations at any one time. Default: `infinity`.
    130 -   `series`: `boolean` indicating whether to sequentially invoke `fcn` for each `collection` element. If `true`, the function sets `options.limit=1`. Default: `false`.
    131 -   `thisArg`: the execution context for `fcn`.
    132 
    133 By default, all elements are processed concurrently, which means that the function does **not** guarantee completion order. To process each `collection` element sequentially, set the `series` option to `true`.
    134 
    135 <!-- eslint-disable no-use-before-define -->
    136 
    137 ```javascript
    138 function fcn( value, index, next ) {
    139     setTimeout( onTimeout, value );
    140     function onTimeout() {
    141         console.log( value );
    142         next( null, value*index );
    143     }
    144 }
    145 
    146 function done( error, collection ) {
    147     if ( error ) {
    148         throw error;
    149     }
    150     console.log( collection === arr );
    151     console.log( collection );
    152 }
    153 
    154 var arr = [ 1000, 2500, 3000 ];
    155 
    156 var opts = {
    157     'series': true
    158 };
    159 
    160 inmapRightAsync( arr, opts, fcn, done );
    161 /* =>
    162     3000
    163     2500
    164     1000
    165     true
    166     [ 0, 2500, 6000 ]
    167 */
    168 ```
    169 
    170 To limit the maximum number of pending function invocations, set the `limit` option.
    171 
    172 <!-- eslint-disable no-use-before-define -->
    173 
    174 ```javascript
    175 function fcn( value, index, next ) {
    176     setTimeout( onTimeout, value );
    177     function onTimeout() {
    178         console.log( value );
    179         next( null, value*index );
    180     }
    181 }
    182 
    183 function done( error, collection ) {
    184     if ( error ) {
    185         throw error;
    186     }
    187     console.log( collection === arr );
    188     console.log( collection );
    189 }
    190 
    191 var arr = [ 1000, 2500, 3000 ];
    192 
    193 var opts = {
    194     'limit': 2
    195 };
    196 
    197 inmapRightAsync( arr, opts, fcn, done );
    198 /* =>
    199     2500
    200     3000
    201     1000
    202     true,
    203     [ 0, 2500, 6000 ]
    204 */
    205 ```
    206 
    207 To set the execution context of `fcn`, set the `thisArg` option.
    208 
    209 <!-- eslint-disable no-use-before-define -->
    210 
    211 ```javascript
    212 function fcn( value, index, next ) {
    213     this.count += 1;
    214     setTimeout( onTimeout, value );
    215     function onTimeout() {
    216         next( null, value*index );
    217     }
    218 }
    219 
    220 var arr = [ 1000, 2500, 3000 ];
    221 
    222 var context = {
    223     'count': 0
    224 };
    225 
    226 var opts = {
    227     'thisArg': context
    228 };
    229 
    230 inmapRightAsync( arr, opts, fcn, done );
    231 
    232 function done( error, collection ) {
    233     if ( error ) {
    234         throw error;
    235     }
    236     console.log( collection === arr );
    237     // => true
    238 
    239     console.log( collection );
    240     // => [ 0, 2500, 6000 ]
    241 
    242     console.log( context.count );
    243     // => 3
    244 }
    245 ```
    246 
    247 When invoked, `fcn` is provided a maximum of four arguments:
    248 
    249 -   `value`: collection value.
    250 -   `index`: collection index.
    251 -   `collection`: the input `collection`.
    252 -   `next`: a callback which should be called once `fcn` has finished processing a collection `value`.
    253 
    254 The actual number of provided arguments depends on function `length`. If `fcn` accepts two arguments, `fcn` is provided `value` and `next`. If `fcn` accepts three arguments, `fcn` is provided `value`, `index`, and `next`. For every other `fcn` signature, `fcn` is provided all four arguments.
    255 
    256 <!-- eslint-disable no-use-before-define -->
    257 
    258 ```javascript
    259 function fcn( value, i, collection, next ) {
    260     console.log( 'collection: %s. %d: %d', collection.join( ',' ), i, value );
    261     setTimeout( onTimeout, value );
    262     function onTimeout() {
    263         console.log( value );
    264         next( null, value*i );
    265     }
    266 }
    267 
    268 function done( error, collection ) {
    269     if ( error ) {
    270         throw error;
    271     }
    272     console.log( collection === arr );
    273     console.log( collection );
    274 }
    275 
    276 var arr = [ 1000, 2500, 3000 ];
    277 
    278 inmapRightAsync( arr, fcn, done );
    279 /* =>
    280     collection: 3000,2500,1000. 2: 3000
    281     collection: 3000,2500,1000. 1: 2500
    282     collection: 3000,2500,1000. 0: 1000
    283     1000
    284     2500
    285     3000
    286     true
    287     [ 0, 2500, 6000 ]
    288 */
    289 ```
    290 
    291 #### inmapRightAsync.factory( \[options,] fcn )
    292 
    293 Returns a `function` which invokes a function once for each element in a `collection`, iterating from right to left.
    294 
    295 ```javascript
    296 function fcn( value, index, next ) {
    297     setTimeout( onTimeout, value );
    298     function onTimeout() {
    299         console.log( value );
    300         next( null, value*index );
    301     }
    302 }
    303 
    304 function done( error, collection ) {
    305     if ( error ) {
    306         throw error;
    307     }
    308     console.log( collection );
    309 }
    310 
    311 var f = inmapRightAsync.factory( fcn );
    312 
    313 var arr1 = [ 1000, 2500, 3000 ];
    314 
    315 f( arr1, done );
    316 /* =>
    317     1000
    318     2500
    319     3000
    320     [ 0, 2500, 6000 ]
    321 */
    322 
    323 var arr2 = [ 100, 250, 300 ];
    324 
    325 f( arr2, done );
    326 /* =>
    327     100
    328     250
    329     300
    330     [ 0, 250, 600 ]
    331 */
    332 ```
    333 
    334 The function accepts the same `options` as `inmapRightAsync()`.
    335 
    336 </section>
    337 
    338 <!-- /.usage -->
    339 
    340 <!-- Package usage notes. Make sure to keep an empty line after the `section` element and another before the `/section` close. -->
    341 
    342 <section class="notes">
    343 
    344 ## Notes
    345 
    346 -   A `collection` may be either an [`Array`][mdn-array], [`Typed Array`][mdn-typed-array], or an array-like [`Object`][mdn-object] (excluding `strings` and `functions`).
    347 -   If a provided function calls the `next` callback with a truthy `error` argument, the function suspends execution and immediately calls the `done` callback for subsequent `error` handling.
    348 -   The function invokes the `done` callback with the input `collection` provided as the second argument.
    349 -   The function modifies `collection` elements in-place.
    350 -   The function does **not** support dynamic `collection` resizing.
    351 -   The function does **not** skip `undefined` elements.
    352 -   **Neither** `inmapRightAsync` nor the function returned by the `factory` method **guarantee** asynchronous execution. To guarantee asynchrony, wrap the `done` callback in a function which either executes at the end of the current stack (e.g., `nextTick`) or during a subsequent turn of the event loop (e.g., `setImmediate`, `setTimeout`).
    353 
    354 </section>
    355 
    356 <!-- /.notes -->
    357 
    358 <!-- Package usage examples. -->
    359 
    360 <section class="examples">
    361 
    362 ## Examples
    363 
    364 <!-- eslint no-undef: "error" -->
    365 
    366 ```javascript
    367 var resolve = require( 'path' ).resolve;
    368 var readFile = require( '@stdlib/fs/read-file' );
    369 var inmapRightAsync = require( '@stdlib/utils/async/inmap-right' );
    370 
    371 var files = [
    372     resolve( __dirname, 'package.json' ),
    373     resolve( __dirname, 'README.md' )
    374 ];
    375 
    376 function done( error, results ) {
    377     if ( error ) {
    378         throw error;
    379     }
    380     console.log( results );
    381 }
    382 
    383 function read( file, next ) {
    384     var opts = {
    385         'encoding': 'utf8'
    386     };
    387     readFile( file, opts, onFile );
    388 
    389     function onFile( error, data ) {
    390         if ( error ) {
    391             error = new Error( 'unable to read file: '+file );
    392             return next( error );
    393         }
    394         next( null, data );
    395     }
    396 }
    397 
    398 inmapRightAsync( files, read, done );
    399 ```
    400 
    401 </section>
    402 
    403 <!-- /.examples -->
    404 
    405 <!-- 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. -->
    406 
    407 <section class="references">
    408 
    409 </section>
    410 
    411 <!-- /.references -->
    412 
    413 <!-- Section for all links. Make sure to keep an empty line after the `section` element and another before the `/section` close. -->
    414 
    415 <section class="links">
    416 
    417 [mdn-array]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array
    418 
    419 [mdn-typed-array]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/TypedArray
    420 
    421 [mdn-object]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object
    422 
    423 </section>
    424 
    425 <!-- /.links -->