# Functional way to create an array of numbers

• A+
Category：Languages

How could I write the following code more functionally using ES6, without any 3rd party libraries?

``// sample pager array // * output up to 11 pages // * the current page in the middle, if page > 5 // * don't include pager < 1 or pager > lastPage // * Expected output using example: //     [9,10,11,12,13,14,15,16,17,18,19]  const page = 14 // by example const lastPage = 40 // by example const pagerPages = page => {   let newArray = []   for (let i = page - 5; i <= page + 5; i++) {     i >= 1 && i <= lastPage ? newArray.push(i) : null   }   return newArray } ``

I would like to avoid Array.push, and possibly the for loop, but I'm not sure how I would achieve it in this situation.

Functional programming isn't limited to `reduce`, `filter`, and `map`; it's about functions. This means we don't have to rely on perverse knowledge like `Array.from ({ length: x })` where an object with a `length` property can be treated like an array. This kind of behavior is bewildering for beginners and mental overhead for anyone else. It think you'll enjoy writing programs that encode your intentions more clearly.

`reduce` starts with 1 or more values and reduces to (usually) a single value. In this case, you actually want the reverse of a `reduce` (or `fold`), here called `unfold`. The difference is we start with a single value, and expand or unfold it into (usually) multiple values.

We start with a simplified example, `alphabet`. We begin unfolding with an initial value of `97`, the char code for the letter `a`. We stop unfolding when the char code exceeds `122`, the char code for the letter `z`.

``const unfold = (f, init) =>   f ( (x, next) => [ x, ...unfold (f, next) ]     , () => []     , init     )  const alphabet = () =>   unfold     ( (next, done, char) =>         char > 122           ? done ()           : next ( String.fromCharCode (char) // value to add to output                  , char + 1                   // next state                  )     , 97 // initial state     )      console.log (alphabet ()) // [ a, b, c, ..., x, y, z ]``

Now we write `pagination`. Here our initial state is compound data `[ page, count ]` instead of a single integer we used above. This demonstrates `unfold` can be used with any seed state, even arrays or objects.

Another advantage to this approach is that you can easily parameterize things like `10` or `- 5` or `+ 1` and there's a sensible, semantic structure to place them in.

``const unfold = (f, init) =>   f ( (x, next) => [ x, ...unfold (f, next) ]     , () => []     , init     )      const pagination = (totalPages, currentPage = 1) =>   unfold     ( (next, done, [ page, count ]) =>         page > totalPages           ? done ()           : count > 10             ? done ()             : next (page, [ page + 1, count + 1 ])     , [ Math.max (1, currentPage - 5), 0 ]     )  console.log (pagination (40, 1)) // [ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11 ]  console.log (pagination (40, 14)) // [ 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19 ]  console.log (pagination (40, 38)) // [ 33, 34, 35, 36, 37, 38, 39, 40 ]  console.log (pagination (40, 40)) // [ 35, 36, 37, 38, 39, 40 ]``

Above, there are two conditions which result in a call to `done ()`. We can collapse these using `||` and the code reads a little nicer

``const pagination = (totalPages, currentPage = 1) =>   unfold     ( (next, done, [ page, count ]) =>         page > totalPages || count > 10           ? done ()           : next (page, [ page + 1, count + 1 ])     , [ Math.max (1, currentPage - 5), 0 ]     ) ``