This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
      Learn more about bidirectional Unicode characters
    
  
  
    
  | // composeFolds :: [(a, x) -> (a | null)] -> ((a, x) -> (a | null)) | |
| // | |
| // `composeFolds` composes reducer functions from left-to-right. | |
| // For example, composeFolds(sum, take(10)) will first call `sum`, | |
| // then `take(10)`. On each iteration of a fold, each reducer receieves | |
| // the aggregate, and the new value (`x`), and returns a new aggregator | |
| // that gets passed along to the next reducer, along with `x`. | |
| // | |
| function composeFolds(...fs) { | |
| return fs.reduce((g, f) => (a, x) => { | 
  
    
      This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
      Learn more about bidirectional Unicode characters
    
  
  
    
  | // An implementation of a range construction with a lazily evaluated forEach | |
| // Usage: | |
| range(1,5).forEachLazy(console.log) //prints 1, 2, 3, 4, 5 | |
| range(1).forEachLazy(console.log) //prints 1, 2... forever | |
| function range(from, to=Infinity) { | |
| const gen = __range(from, to) | |
| gen.forEachLazy = __forEachLazy(gen) | 
  
    
      This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
      Learn more about bidirectional Unicode characters
    
  
  
    
  | // Function Spread | |
| // https://medium.com/@anirudheka/how-to-use-the-spread-operator-on-a-function-b7dd9d13752a?sk=b85ebf2107d618184ad4e44a2270835f | |
| const spread = (...fns) => | |
| fns.reduce((a, f) => x => { | |
| const v = f(x) | |
| return v !== undefined ? v : a(x) | |
| }) | |
| // usage | 
  
    
      This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
      Learn more about bidirectional Unicode characters
    
  
  
    
  | const mapping = mapLogic => reducer => (a, x) => { | |
| const transformed = mapLogic(x); | |
| return reducer(a, transformed) | |
| } | |
| const filtering = filterLogic => reducer => (a, x) => { | |
| if(filterLogic(x)) { | |
| return reducer(a, x) | |
| } else { | |
| return a; | 
  
    
      This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
      Learn more about bidirectional Unicode characters
    
  
  
    
  | const mapAdd1Transducer = reducer => (a, x) => { | |
| const transformed = x + 1; | |
| return reducer(a, transformed) | |
| } | |
| const filterGreaterThan2Transducer = reducer => (a, x) => { | |
| if(x > 2) { | |
| return reducer(a, x) | |
| } else { | |
| return a; | |
| } | 
  
    
      This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
      Learn more about bidirectional Unicode characters
    
  
  
    
  | const mapAdd1Reducer = (a, x) => { | |
| const transformed = x + 1; | |
| return a.concat(transformed) | |
| } | |
| const filterGreaterThan2Transducer = reducer => (a, x) => { | |
| if(x > 2) { | |
| return reducer(a, x) | |
| } else { | |
| return a; | 
  
    
      This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
      Learn more about bidirectional Unicode characters
    
  
  
    
  | const filterGreaterThan2AndMapAdd1Reducer = (a, x) => { | |
| if(x > 2) { | |
| return mapAdd1Reducer(a, x) | |
| } else { | |
| return a; | |
| } | |
| } | |
| [1, 2, 3].reduce(filterGreaterThan2AndMapAdd1Reducer, []); | 
  
    
      This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
      Learn more about bidirectional Unicode characters
    
  
  
    
  | const mapAdd1Reducer = (a, x) => { | |
| const transformed = x + 1; | |
| return a.concat(transformed) | |
| } | |
| const filterGreaterThan2Reducer = (a, x) => { | |
| if(x > 2) { | |
| return a.concat(x) | |
| } else { | |
| return a; | |
| } | 
  
    
      This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
      Learn more about bidirectional Unicode characters
    
  
  
    
  | const jayZDetailsFn = (k) => jayZDetails[k]; | |
| const intermediateResult = mapFn(stringifyNumber, jayZDetailsFn); | |
| //=> x => stringifyNumber(jayZDetailsFn(x)) | |
| const result = mapFn(addAgeSuffix,intermediateResult); | |
| //=> x => addAgeSuffix(stringifyNumber(jayZDetailsFn(x))) | |
| result('demeanorAge') //=> 'seventy eight years old'; | 
  
    
      This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
      Learn more about bidirectional Unicode characters
    
  
  
    
  | const jayZDetails = { age: 48, demeanorAge: 78 }; | |
| const intermediateResult = mapObj(stringifyNumber, jayZDetails); | |
| // => { age: 'forty eight', demeanorAge: 'seventy eight' } | |
| const finalResult = mapObj(addAgeSuffix, intermediateResult)); | |
| // => { age: 'forty eight years old', demeanorAge: 'seventy eight years old' } | |
| result['demeanorAge'] //=> 'seventy eight years old'; | 
NewerOlder