time-to-botec

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

README.md (10292B)


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