DEV Community

Cover image for Ranger: JS Range Syntax for Anything
Jon Randy 🎖️
Jon Randy 🎖️

Posted on • Edited on

Ranger: JS Range Syntax for Anything

Following on from my little experiment with a basic number range syntax in JS, I decided (as with Metho and Turboprop) to generalise the idea and make it into a library that others might find useful (or at least interesting)...

Ranger is a small JS library that allows you to use a range-like syntax with any object. All you need to do is to define a function that builds the required 'range' given a starting and ending object (+ optional extra parameters if you so desire).

The 'range' syntax is as follows:

rangeStart[[...rangeEnd, optionalParam1, optionalParam2...]]

So, for example, if you created a range function for Numbers - you could then use it like this:

// create a range of numbers from 1-10
const numbers = 1[[...10]]

// log the numbers from 6-3
6[[...3]].forEach(x => console.log(x))
Enter fullscreen mode Exit fullscreen mode

How to Use

Usage is extremely simple, just import the library and use it to set up the range function on your required object (usually this would be a prototype):

import * as ranger from '@jonrandy/js-ranger'

const myRangeFunction = (start, end) => {
  // logic to return 'range' here
}
ranger.attach(myObject, myRangeFunction)
Enter fullscreen mode Exit fullscreen mode

If you pass in optional parameters according to the syntax detailed at the start of this README, they will simply be passed as additional arguments to your range function. Your 'range' making function can return anything - it doesn't have to be an array.

Number Ranges

Also exported by the library as an example of usage is a function called initNumberRangeSyntax that sets up a basic range syntax on the Number prototype - that does pretty much what you would expect. It can also take an additional stepSize parameter that defaults to 1 and decides the (absolute) size of the steps between items in the range:

import * as ranger from '@jonrandy/js-ranger'
ranger.initNumberRangeSyntax()
console.log(1[[...3]])  // [1, 2, 3]
console.log(5[[...2]])  // [5, 4, 3, 2]
console.log(0[[...3, 0.75]]) // [0, 0.75, 1.5, 2.25, 3]
console.log(2[[...0, 0.5]]) // [2, 1.5, 1, 0.5, 0]
Enter fullscreen mode Exit fullscreen mode

And the source for initNumberRangeSyntax():

export function initNumberRangeSyntax() {
  attach(Number.prototype, (start, end, stepSize = 1) => {
    const absStep = stepSize<0 ? Math.abs(stepSize) : stepSize
    const step = start<=end ? absStep : -absStep
    let arr = [], i, d = end > start
    for (i=+start; d ? i<=end : i>=end; i+=step) arr.push(i)
    return arr
  })
}
Enter fullscreen mode Exit fullscreen mode

UPDATE: It has been pointed out that returning an iterator would probably be more efficient and allow for dealing with infinite ranges. That is just as possible with Ranger - simply return a generator function:

// Number ranges as iterators
attach(Number.prototype, function* (start, end, stepSize = 1) {
  const absStep = stepSize<0 ? Math.abs(stepSize) : stepSize
  const step = start<=end ? absStep : -absStep
  let arr = [], i, d = end > start
  for (i=+start; d ? i<=end : i>=end; i+=step) yield i
})

Enter fullscreen mode Exit fullscreen mode

Possible Usages

This was written as a general purpose tool that could have any number of potential uses. Some random ideas:

const myDateRange = date1[[...date2]]
const myRoute = location1[[...location2, {via: location3}]]
const myLine = point1[[...point2]]
const translator = language1[[...language2]] // could return a function that takes strings in one language and translates to another
Enter fullscreen mode Exit fullscreen mode

GitHub logo jonrandy / js-ranger

Javascript library to add range syntax functionality to any object

Ranger

Ranger is a small JS library that allows you to use a range-like syntax with any object. All you need to do is to define a function that builds the required 'range' given a starting and ending object (+ optional extra parameters if you so desire).

The 'range' syntax is as follows:

rangeStart[[...rangeEnd, optionalParam1, optionalParam2...]]

So, for example, if you created a range function for Numbers - you could then use it as follows:

// create a range of numbers from 1-10
const numbers = 1[[...10]]
// log the numbers from 6-3
6[[...3]].forEach(x => console.log(x))
Enter fullscreen mode Exit fullscreen mode

How to Use

Usage is extremely simple, just import the attach function and use it to set up the range function on your required object:

import { attach }
Enter fullscreen mode Exit fullscreen mode

Top comments (2)

Collapse
 
activenode profile image
David Lorenz

I do love those digging-deep things into JS. They are what make JS valuable to me.

Collapse
 
sethcalebweeks profile image
Caleb Weeks

I have been really enjoying these JavaScript syntax hacks. Also, this article was just featured here: javascriptweekly.com/issues/634. Congrats!