# Range Syntax

**URL:** <https://es.discourse.group/t/range-syntax/261>\
**Category:** 💡 Ideas\
**Tags:** proposal\
**Created:** [March 12, 2020, 2:35pm UTC](https://es.discourse.group/t/range-syntax/261 "2020-03-12T14:35:31Z")\
**Posts on this page:** 4\
**Page:** 1

<div class="post-metadata">

**Author:** ![oauo](https://yyz2.discourse-cdn.com/free1/user_avatar/es.discourse.group/oauo/32/269_2.png) [@oauo](https://es.discourse.group/u/oauo)\
**Post date:** [March 12, 2020, 2:35pm UTC](https://es.discourse.group/t/range-syntax/261/1 "2020-03-12T14:35:31Z")

</div>

_[Read on GitHub](https://github.com/oauo/Range-Proposal)_

# JavaScript Range Proposal

This is a proposal to add a way to define ranges of numbers in a straight forward manner without requiring a hacky or long winded solution.

I feel this is different to other similar proposals in that this would make it more as a part of arrays rather than another function which would make it far smoother and easier to use

## This feature exists in other languages

- Haskell `[a..b]` & `[a,n..b]`
- F# `[|a..b|]` & `[|a..n..b|]`
- PHP `range(a,b)` & `range(a,b,n)`
- R `a:b` & `seq(a,b,by=n)`

## Limited alternatives in other languages

- C# `Enumerable.Range(a, b)`
- Python `range(a, b+1)`
- Java `Range.between(a, b)`
- Coffeescript `a..b`

## Motivation

The current solution in JavaScript to get a range of numbersfrom a to b (inclusive) is to use a solution which applies the keys of an array into another array and then mapping to move to start at `a`

```
[...new Array(b-a+1).keys()].map(x => x+a)

```

And if a step is required

```
[...new Array(Math.floor((b-a)/n)+1).keys()].map(x => n*x+a)

```

I find myself needing to use an equivilant of `[0..b]` and `[0..n..b]` all the time but the solutions for those are bulky. Other languages have a way to do this an intended way and it would be a useful tool to have access to.

## Basic Idea

I propose that a syntax similar to F# should be used. `a` is first number (not necessarily smallest), `b` is last number (not necessarily the biggest), and `n` is the gap.

Ranges would be `a` to `b` by optional `n` (multiple) inclusive.

## Example Usage

The example codes below shows intended syntax, output, and JS equivilant

### a to b

#### Explicit bounds

```
[1..5] = [1,2,3,4,5] [...new Array(b-a+1).keys()].map(x => a+x)
[6..3] = [6,5,4,3] [...new Array(a-b+1).keys()].map(x => a-x)

```

#### Implicit bounds

Missing bounds are implicitly `0`

```
[..4] = [0,1,2,3,4] [...new Array(b+1).keys()]
[2..] = [2,1,0] [...new Array(a+1).keys()].map(x=>a-x)

```

### a to b by n

Ranges stepping by `n` will not go past `b`

#### Explicit bounds

```
[1..2..5] = [1,3,5] [...new Array(Math.floor((b-a)/n)+1).keys()].map(x => n*x+a)
[1..2..6] = [1,3,5]
[5..2..1] = [5,3,1] [...new Array(Math.floor((a-b)/n)+1).keys()].map(x => a-n*x)
[6..2..1] = [6,4,2]

```

#### Implicit bounds

Missing bounds are implicitly `0`

```
[..2..5] = [0,2,4] [...new Array(Math.floor(b/n)+1).keys()].map(x => n*x)
[..2..6] = [0,2,4,6]
[5..2..] = [5,3,1] [...new Array(Math.floor(a/n)+1).keys()].map(x => a-n*x)
[6..2..] = [6,4,2,0]

```

## Further Ideas

### Multiple gaps

These gaps would alternate applying, so gaps `1` and `2` would add `1` then `2` and stops before going over `b`

```
[1..1..2..10] = [1,2,4,5,7,8,10]
[1..0..1..4] = [1,1,2,2,3,3,4,4]

let abns = (a,b,...n) => {
    let arr = [], p = a, i = 0
    for(let p = a; p <= b; p+=n[i++%n.length])
        arr.push(p)
    return arr
}

```

### Float ranges

```
[0..0.2..1] = [0,0.2,0.4,0.6,0.8,1]
[0...2..1] = [0,0.2,0.4,0.6,0.8,1] //Without leading 0
[0.5..3] = [0.5,1.5,2.5]
[0..1..2.2] = [0,1,2]

```

## Open Questions

- If `a` and `b` are missing, would it throw an error or return `[0]`

```
[..] = [0..0] = [0]
[..2..] = [0..2..0] = [0]

```

- If `n` i missing, would it interpret it as `1`, this might be useful for [multiple gaps](#multiple-gaps) but could be confusing and doesn't present any benefit

```
[2....5] = [2..1..5] = [2,3,4,5]
[1..0....4] = [1..0..1..4] = [1,1,2,2,3,3,4,4]
[1....0......3] = [1..1..0..1..1..7] = [1,2,2,3,4,5,5,6,7]

```

- Is `..` too ambigious in some situations and could be replaced with `:`, would also make it smaller

```
[1:4] = [1,2,3,4]
[3:2:8] = [3,5,7]
[1.3:.2:2.5] = [1.3,1.5,1.7,1.9,2.1,2.3,2.5]

```

## Alternatives

- You can do everything with applying an array's keys to another array but it's unnecessarily complicated
- [Lodash](https://lodash.com/) does have [`_.range(a,b,n?)`](https://lodash.com/docs/4.17.15#range)
- Coffeescript has [`[a..b]`](https://coffeescript.org/#loops) (scroll down to the section below)

---

<div class="post-metadata">

**Author:** ![devsnek](https://yyz2.discourse-cdn.com/free1/user_avatar/es.discourse.group/devsnek/32/100_2.png) [@devsnek](https://es.discourse.group/u/devsnek)\
**Post date:** [March 13, 2020, 9:33pm UTC](https://es.discourse.group/t/range-syntax/261/2 "2020-03-13T21:33:51Z")

</div>

[https://github.com/Jack-Works/proposal-Number.range](https://github.com/Jack-Works/proposal-Number.range) is being presented at the next TC39 meeting.

---

<div class="post-metadata">

**Author:** ![Crissov](https://yyz2.discourse-cdn.com/free1/user_avatar/es.discourse.group/crissov/32/217_2.png) [@Crissov](https://es.discourse.group/u/Crissov)\
**Post date:** [March 14, 2020, 10:29am UTC](https://es.discourse.group/t/range-syntax/261/3 "2020-03-14T10:29:52Z")

</div>

In particular, it says in subsection _Other_:

> - Add a new syntax like `2...3` instead of a `Number.range()`?

That is, decide whether two dots `..`, three dots `...` or a colon `:` would be best.

---

<div class="post-metadata">

**Author:** ![oauo](https://yyz2.discourse-cdn.com/free1/user_avatar/es.discourse.group/oauo/32/269_2.png) [@oauo](https://es.discourse.group/u/oauo)\
**Post date:** [March 26, 2020, 11:00pm UTC](https://es.discourse.group/t/range-syntax/261/4 "2020-03-26T23:00:07Z")

</div>

Thank you, opened an issue to suggest things from this proposal
