2018-09-28 13:59:05 +03:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								# walk.js
  
						 
					
						
							
								
									
										
										
										
											2018-09-28 15:36:27 +03:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2018-09-28 13:59:05 +03:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								An extensible tree walk(..) framework...
							 
						 
					
						
							
								
									
										
										
										
											2018-09-28 15:36:27 +03:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2018-09-29 23:44:44 +03:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2018-09-30 01:48:59 +03:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								-  [walk.js ](#walkjs ) 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									-  [Theory and operation ](#theory-and-operation )
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										-  [Constructing the walker and walking ( walk(..) ) ](#constructing-the-walker-and-walking--walk )
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										-  [Getting and processing nodes ( getter(..) ) ](#getting-and-processing-nodes--getter )
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										-  [Putting it all together ](#putting-it-all-together )
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									-  [Installation and loading ](#installation-and-loading )
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									-  [API ](#api )
							 
						 
					
						
							
								
									
										
										
										
											2018-09-30 03:08:59 +03:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										-  [`walk(..)` ](#walk )
							 
						 
					
						
							
								
									
										
										
										
											2018-10-04 13:39:02 +03:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
											-  [`getter(..)` ](#getter )
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											-  [`done(..)` ](#done )
							 
						 
					
						
							
								
									
										
										
										
											2018-09-30 01:48:59 +03:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									-  [Examples ](#examples )
							 
						 
					
						
							
								
									
										
										
										
											2018-10-04 13:39:02 +03:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									-  [Contacts, feedback and contributions ](#contacts-feedback-and-contributions )
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									-  [License ](#license )
							 
						 
					
						
							
								
									
										
										
										
											2018-09-30 01:48:59 +03:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2018-09-28 15:36:27 +03:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								## Theory and operation
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2018-10-01 00:04:08 +03:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								This module generalizes structure traverse (*walking*, recursion). This is done via a `walk(..)`  function that recieves a user-defined `getter(..)`  function and returns a *walker* .
							 
						 
					
						
							
								
									
										
										
										
											2018-09-29 23:44:44 +03:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2018-09-30 01:48:59 +03:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								### Constructing the walker and walking ( walk(..) )
  
						 
					
						
							
								
									
										
										
										
											2018-09-28 15:36:27 +03:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2018-09-30 01:48:59 +03:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								`walk(getter[, done])(state, ...nodes) -> state`    
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								`walk(getter[, done], state)(...nodes) -> state`    
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								`walk(getter[, done], state, ...nodes) -> state`    
						 
					
						
							
								
									
										
										
										
											2018-09-30 03:54:40 +03:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								-  Recieves a `getter(..)`  function, an optional `done(..)`  function, a `state`  and a list of `nodes` , 
						 
					
						
							
								
									
										
										
										
											2018-09-30 01:48:59 +03:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								-  Iterates through `nodes` , calling the `getter(..)`  per node and threading the `state`  through each call, 
						 
					
						
							
								
									
										
										
										
											2018-09-30 03:54:40 +03:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								-  If `done(..)`  is given, it is called after *walking*  is done, threading `state`  through, 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								-  Returns the `state`  when walking is done. 
						 
					
						
							
								
									
										
										
										
											2018-09-28 15:36:27 +03:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2018-09-29 23:44:44 +03:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2018-09-30 01:48:59 +03:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								### Getting and processing nodes ( getter(..) )
  
						 
					
						
							
								
									
										
										
										
											2018-09-29 23:44:44 +03:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2018-09-30 00:16:09 +03:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								`getter(state, node, next, stop) -> state`    
						 
					
						
							
								
									
										
										
										
											2018-09-30 03:54:40 +03:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2018-09-30 00:16:09 +03:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								-  Recieves `state` , `node`  and two control functions: `next`  and `stop` , 
						 
					
						
							
								
									
										
										
										
											2018-09-30 23:48:47 +03:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								-  Called in a context (`this` ), persistent within one `walk(..)`  call, inherited from *walker's*  `.prototype` . This context is usable to store data between `getter(..)`  calls, 
						 
					
						
							
								
									
										
										
										
											2018-09-28 15:36:27 +03:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								-  Can process `node`  and `state` , 
						 
					
						
							
								
									
										
										
										
											2018-09-30 03:54:40 +03:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								-  Can queue nodes for walking via `next('queue', state, ...nodes) -> state` , 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								-  Can walk nodes directly via `next('do', state, ...nodes) -> state` , 
						 
					
						
							
								
									
										
										
										
											2018-09-30 23:48:47 +03:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								-  Can abort *walking*  and return a state via `stop()`  (returning `undefined` ) or `stop(state)` , 
						 
					
						
							
								
									
										
										
										
											2018-09-30 03:54:40 +03:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								-  Returns `state` . 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2018-09-30 23:48:47 +03:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								`state`  is *threaded*  through all the `getter(..)`  and `done(..)`  calls, i.e. the first call gets the input `state` , each next call gets the previous call's returned `state`  passed in, then its returned `state`  gets passed on, and so on. The last function's returned `state`  is in turn returned from the *walker* . 
						 
					
						
							
								
									
										
										
										
											2018-09-30 03:54:40 +03:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2018-09-30 23:48:47 +03:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								Within a single *walker*  call, all the `getter(..)`  and `done(..)`  calles a run in one common context. This context can be used to store (*thread*)additional temporary data through the *walker* . This context is dropped as soon as the *walker*  returns. This context object is inherited from *walker's*  `.prototype`  enabling the user to define persistent methods and static data usable from within the *walker's*  `getter(..)`  and `done(..)` .
							 
						 
					
						
							
								
									
										
										
										
											2018-09-28 15:36:27 +03:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2018-09-29 23:44:44 +03:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								### Putting it all together
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2018-09-28 15:36:27 +03:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								A trivial *flat*  example...
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								```javascript
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								walk(function(r, n){ return r+n }, 0, ...[1,2,3]) // -> 6
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								```
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								The above is essentially equivalent to...
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								```javascript
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								[1,2,3].reduce(function(r, n){ return r+n }, 0) // -> 6
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								```
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2018-09-29 23:44:44 +03:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								And for *flat*  lists `.reduce(..)`  and friends are simpler and more logical. `walk(..)`  is designed to simplify more complex cases:
							 
						 
					
						
							
								
									
										
										
										
											2018-09-28 15:36:27 +03:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								-  The input is not *flat* : 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									```javascript
							 
						 
					
						
							
								
									
										
										
										
											2018-09-29 23:44:44 +03:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									// sum the items in a *deep*  array (depth-first)...
							 
						 
					
						
							
								
									
										
										
										
											2018-09-30 00:16:09 +03:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									var sum = walk(function(r, n, next){
							 
						 
					
						
							
								
									
										
										
										
											2018-09-28 15:36:27 +03:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										return n instanceof Array ?
							 
						 
					
						
							
								
									
										
										
										
											2018-09-30 01:59:57 +03:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
											next('do', r, ...n)
							 
						 
					
						
							
								
									
										
										
										
											2018-09-28 15:36:27 +03:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
											: r + n }, 0) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									sum( [1, [2, 3], 4, [[5], 6]] ) // -> 21
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									```
							 
						 
					
						
							
								
									
										
										
										
											2018-09-30 00:16:09 +03:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									For reference here is a *recursive*  `.reduce(..)`  example, already a bit more complex:
							 
						 
					
						
							
								
									
										
										
										
											2018-09-28 15:47:58 +03:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									```javascript
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									function sumr(l){
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										return l.reduce(function(r, e){
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											return r + (e instanceof Array ?
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												sumr(e)
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												: e) }, 0) }
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									sumr( [1, [2, 3], 4, [[5], 6]] ) // -> 21
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									```
							 
						 
					
						
							
								
									
										
										
										
											2018-09-29 23:44:44 +03:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2018-09-28 15:36:27 +03:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								-  Need to abort the recursion prematurelly: 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									```javascript
							 
						 
					
						
							
								
									
										
										
										
											2018-09-28 15:47:58 +03:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									// check if structure contains 0...
							 
						 
					
						
							
								
									
										
										
										
											2018-09-30 00:16:09 +03:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									var containsZero = walk(function(r, e, next, stop){
							 
						 
					
						
							
								
									
										
										
										
											2018-09-29 03:13:46 +03:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										// NOTE: we'll only count leaf nodes...
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										this.nodes_visited = (this.nodes_visited || 0)
							 
						 
					
						
							
								
									
										
										
										
											2018-09-28 15:36:27 +03:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										return e === 0 ? 
							 
						 
					
						
							
								
									
										
										
										
											2018-09-30 00:16:09 +03:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
												// abort search, report number of nodes visited...
							 
						 
					
						
							
								
									
										
										
										
											2018-09-29 03:13:46 +03:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
												stop(this.nodes_visited+1)
							 
						 
					
						
							
								
									
										
										
										
											2018-09-28 15:36:27 +03:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
											: e instanceof Array ?
							 
						 
					
						
							
								
									
										
										
										
											2018-09-30 02:01:03 +03:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
												next('do', ...e)
							 
						 
					
						
							
								
									
										
										
										
											2018-09-29 03:13:46 +03:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
											: (this.nodes_visited++, r) }, false)
							 
						 
					
						
							
								
									
										
										
										
											2018-09-28 15:36:27 +03:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2018-09-29 03:13:46 +03:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									containsZero( [1, [2, 0], 4, [[5], 6]] ) // -> 3
							 
						 
					
						
							
								
									
										
										
										
											2018-09-28 15:36:27 +03:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									containsZero( [1, [2, 5], 4, [[5], 6]] ) // -> false
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									```
							 
						 
					
						
							
								
									
										
										
										
											2018-09-28 15:47:58 +03:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									See a more usefull search in [examples ](#examples )...
							 
						 
					
						
							
								
									
										
										
										
											2018-09-28 15:36:27 +03:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2018-09-30 01:48:59 +03:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2018-09-28 15:36:27 +03:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								## Installation and loading
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								```shell
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								$ npm install --save generic-walk
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								```
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								```javascript
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								var walk = require('generic-walk').walk
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								```
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2018-09-30 02:03:41 +03:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								*Note: This module supports both [`requirejs(..)` ](https://requirejs.org ) and node's `require(..)` **
							 
						 
					
						
							
								
									
										
										
										
											2018-09-28 15:36:27 +03:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2018-09-30 01:48:59 +03:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2018-09-28 15:36:27 +03:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								## API
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2018-09-30 03:08:59 +03:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								### `walk(..)`
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2018-09-28 15:36:27 +03:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								`walk(getter(..)) -> walker(state, ...nodes)`    
						 
					
						
							
								
									
										
										
										
											2018-09-30 01:48:59 +03:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								`walk(getter(..), done(..)) -> walker(state, ...nodes)`    
						 
					
						
							
								
									
										
										
										
											2018-09-28 15:36:27 +03:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								Construct a reusable walker.
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								`walk(getter(..), state) -> walker(...nodes)`    
						 
					
						
							
								
									
										
										
										
											2018-09-30 01:48:59 +03:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								`walk(getter(..), done(..), state) -> walker(...nodes)`    
						 
					
						
							
								
									
										
										
										
											2018-09-28 15:36:27 +03:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								Construct a reusable walker with fixed initial state.
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								`walk(getter(..), state, ...nodes) -> result`    
						 
					
						
							
								
									
										
										
										
											2018-09-30 01:48:59 +03:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								`walk(getter(..), done(..), state, ...nodes) -> result`    
						 
					
						
							
								
									
										
										
										
											2018-09-28 15:36:27 +03:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								Walk the nodes.
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2018-09-30 03:08:59 +03:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								*Note that `state`  can not be a function unless `done(..)`  is provided.*
							 
						 
					
						
							
								
									
										
										
										
											2018-09-30 01:48:59 +03:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2018-09-28 15:36:27 +03:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2018-10-04 13:39:02 +03:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								#### `getter(..)`
  
						 
					
						
							
								
									
										
										
										
											2018-09-28 15:36:27 +03:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2018-09-30 00:16:09 +03:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								`getter(state, node, next(..), stop(..)) -> state`    
						 
					
						
							
								
									
										
										
										
											2018-09-30 03:08:59 +03:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								User provided function, called to process a node. `getter(..)`  is passed the current `state` , the `node`  and two control functions: `next(..)`  and `stop(..)`  to control the *walk*  execution flow.
							 
						 
					
						
							
								
									
										
										
										
											2018-09-28 15:36:27 +03:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2018-09-30 03:54:40 +03:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								*`next('queue', state, ...nodes) -> state` *  
							 
						 
					
						
							
								
									
										
										
										
											2018-09-30 03:08:59 +03:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								Queue `nodes`  for walking (*breadth-first*). The queued nodes will get *walked*  after this level of nodes is done, i.e. after the `getter(..)`  is called for each node on current level.
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2018-10-09 00:56:41 +03:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								*Note that this does not change the state in any way and returns it as-is, this is done for signature compatibility with `next('do', ..)` .*  
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								*Note that a common instinct here is to expect to get a promise as a result of `next('queue', ..)` , this is not needed as the `getter(..)`  will eventually get all the queued nodes as input anyway and adding promises into the mix would only complicate things.*
							 
						 
					
						
							
								
									
										
										
										
											2018-09-28 15:36:27 +03:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2018-09-30 03:54:40 +03:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								*`next('do', state, ...nodes) -> state` *  
							 
						 
					
						
							
								
									
										
										
										
											2018-09-30 03:08:59 +03:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								Walk `nodes`  (*depth-first*) and return `state` . The nodes will get *walked*  immidiately.
							 
						 
					
						
							
								
									
										
										
										
											2018-09-28 15:36:27 +03:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2018-09-30 03:54:40 +03:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								*`stop()` *  
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								*`stop(state)` *  
							 
						 
					
						
							
								
									
										
										
										
											2018-09-28 15:36:27 +03:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								Stop walking and return `state` . The passed `state`  is directly returned from the *walker* .
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								*Note that `stop(..)`  behaves in a similar manner to `return` , i.e. execution is aborted immidiately.*
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2018-10-04 13:39:02 +03:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								#### `done(..)`
  
						 
					
						
							
								
									
										
										
										
											2018-09-30 01:48:59 +03:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								`done(state) -> state`    
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								User provided function, if given, is called by the *walker*  after walking is done (no more nodes to handle). `state`  is passed as argument and the return value is returned from the *walker* . This is run in the same context (`this` ) as `getter(..)` .
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2018-09-28 15:36:27 +03:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								## Examples
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								Sum all the values of a nested array (breadth-first)...
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								```javascript
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								var sum = walk(function(res, node, next){
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									return node instanceof Array ?
							 
						 
					
						
							
								
									
										
										
										
											2018-09-30 00:16:09 +03:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										next('queue', res, ...node) 
							 
						 
					
						
							
								
									
										
										
										
											2018-09-28 15:36:27 +03:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										: res + node }, 0)
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								sum([1, [2], 3, [[4, 5]]]) // -> 15 ...walks the nodes: 1, 3, 2, 4, 5
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								```
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								Sum all the values of a nested array (depth-first)...
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								```javascript
							 
						 
					
						
							
								
									
										
										
										
											2018-09-30 00:16:09 +03:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								var sumd = walk(function(res, node, next){
							 
						 
					
						
							
								
									
										
										
										
											2018-09-28 15:36:27 +03:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									return node instanceof Array ?
							 
						 
					
						
							
								
									
										
										
										
											2018-09-30 00:16:09 +03:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										// yes, this is the only difference...
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										next('do', res, ...node)
							 
						 
					
						
							
								
									
										
										
										
											2018-09-28 15:36:27 +03:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										: res + node }, 0)
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								sumd([1, [2], 3, [[4, 5]]]) // -> 15 ...walks the nodes: 1, 2, 3, 4, 5
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								```
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2018-09-29 23:44:44 +03:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								To explicitly see the paths the `sum` /`sumd`  take we need to modify them a little:
							 
						 
					
						
							
								
									
										
										
										
											2018-09-28 15:36:27 +03:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								```javascript
							 
						 
					
						
							
								
									
										
										
										
											2018-09-30 00:16:09 +03:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								var makeSummer = function(mode){
							 
						 
					
						
							
								
									
										
										
										
											2018-09-30 01:48:59 +03:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									var walker = walk(
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										function(res, node, next){
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											this.log(node)
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											return node instanceof Array ?
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												next(mode == 'breadth-first' ? 'queue' : 'do', 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
													res, 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
													...node) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												: res + node },
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										// print the path when done...
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										function(state){
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											console.log('-->', this.path)
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											return state
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										}, 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										1) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									// log the nodes...
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									walker.prototype.log = function(node){
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										this.path = node instanceof Array ?
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											this.path
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											: (this.path || []).concat([node]) } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									return walker
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}
							 
						 
					
						
							
								
									
										
										
										
											2018-09-30 00:16:09 +03:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								var sum = makeSummer('breadth-first')
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								var sumd = makeSummer('depth-first')
							 
						 
					
						
							
								
									
										
										
										
											2018-09-28 15:36:27 +03:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2018-09-29 03:13:46 +03:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								sum([1, [2], 3, [[4, 5]]]) // -> 15
							 
						 
					
						
							
								
									
										
										
										
											2018-09-28 15:36:27 +03:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2018-09-29 03:13:46 +03:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								sumd([1, [2], 3, [[4, 5]]]) // -> 15
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								```
							 
						 
					
						
							
								
									
										
										
										
											2018-09-28 15:36:27 +03:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								FInd first zero in tree and return it's path...
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								```javascript
							 
						 
					
						
							
								
									
										
										
										
											2018-09-29 03:13:46 +03:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								// NOTE: the only reason this is wrapped into a function is that we need
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								//  	to restrict the number of items (L) this is passed to 1...
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								var firstZero = function(L){
							 
						 
					
						
							
								
									
										
										
										
											2018-09-30 00:16:09 +03:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									return walk(function(res, node, next, stop){
							 
						 
					
						
							
								
									
										
										
										
											2018-09-29 03:13:46 +03:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										// setup...
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										if(this.path == null){
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											this.path = []
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											node = [null, node]
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										}
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										var path = this.path
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										var k = node[0]
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										var v = node[1]
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										return v === 0 ?
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												// NOTE: we .slice(1) here to remove the initial null
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												//		we added in firstZero(..)...
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												stop(path.slice(1).concat([k]))
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											: v instanceof Object?
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												(path.push(k), 
							 
						 
					
						
							
								
									
										
										
										
											2018-09-30 00:16:09 +03:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
												next('do', res, ...Object.entries(v)))
							 
						 
					
						
							
								
									
										
										
										
											2018-09-29 03:13:46 +03:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
											: res}, false, L) }
							 
						 
					
						
							
								
									
										
										
										
											2018-09-28 15:36:27 +03:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								firstZero([10, 5, [{x: 1, y: 0}, 4]]) // -> ['2', '0', 'y']
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								```
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2018-10-04 13:39:02 +03:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								## Contacts, feedback and contributions
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								-  https://github.com/flynx/walk.js 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								-  https://www.npmjs.com/generic-walk 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								-  https://github.com/flynx 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								## License
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								[BSD 3-Clause License ](./LICENSE )
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								Copyright (c) 2018, Alex A. Naanou,
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								All rights reserved.