O que é a nova propostas de sequências com o Iterator.range no JavaScript
Tags: javascript, ecmascript, development, typescript
Published: 2023-03-13 21:54:19

---
title: O que é a nova propostas de sequências com o Iterator.range no JavaScript
published: true
date: 2023-02-09 10:00:30 UTC
tags: javascript,ecmascript,development,typescript
canonical_url: https://blog.lsantos.dev/number-range/
cover_image: https://raw.githubusercontent.com/khaosdoctor/blog-assets/master/images/2023/02/articles-1.png
---

As vezes as propostas mais simples são as que trazem mais valor para algum projeto, e com essa não foi diferente.

Várias linguagens, uma delas, por exemplo, o Python, possuem estruturas para representar e até mesmo criar sequencias de números naturais de uma forma simples. O JavaScript ainda não tinha essa capacidade, e ela foi extensivamente requisitada em diversos projetos.

Mas a espera acabou, hoje a gente vai falar da [proposta](https://github.com/tc39/proposal-Number.range) que vai adicionar o método `range` a um iterador. Essa é uma proposta que está no início (não passou do **estágio 1)**, mas é extremamente promissora!

Se você não sabe como funciona o JavaScript, nesse vídeo eu explico um pouco mais sobre o processo de lançamento de novas funcionalidades do JavaScript, se você ainda não assistiu, eu recomendo fortemente para poder entender melhor como tudo funciona!

<iframe width="200" height="113" src="https://www.youtube.com/embed/hDQu3AvvDfg?feature=oembed" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture" allowfullscreen title="Como o JavaScript Evolui - entendendo as propostas do TC39"></iframe>

# Ranges

Ranges ou sequências são meta-estruturas de uma linguagem, ou seja, elas existem em teoria, mas essencialmente são só um encapsulamento de uma lógica mais simples transformada em um construto de uma linguagem. Ranges são simplesmente uma sequência de números, com um valor mínimo, um valor máximo e um valor opcional chamado `step` que é a quantidade de números que vamos pular de cada vez.

Ranges são úteis para uma variedade de coisas, mas um dos principais usos é uma alternativa a um iterador, ao invés de fazer algo como:

```
for (let i = 0; i < 10; i++) { ... }
```

Você poderia fazer uma chamada mais simples. Por exemplo, no Python, você pode gerar um range de números que vai de 0 a 9 usando esse código:

```
for n in range(10):
	print(n)
```

Esse código vai printar números indo de 0 até 9 no console, mas você pode fazer a mesma coisa usando um `for` simples e contando de 0 até 9, por exemplo, no JavaScript seria algo assim:

```
let x = [0]
for (let i = 0; i <= 9; i++) {
    x.push(i+1)
}

```

São mais passos e mais código, e é justamente para isso que essa proposta chegou. Inclusive, ela não tem nenhum objetivo especial de melhorar performance, ou até mesmo de deixar a contagem mais eficiente, é pura e simplesmente pelo fato de que todas as outras linguagens também tem, e uma linguagem sem um `range` parece incompleta.

> Esse é um daqueles tipos de funções que é super simples e tem alguns usos específicos que você não tem como escapar, da mesma forma que a intersecção de dois arrays, ou a diferença entre eles. É simples demais para não estar embutido na linguagem.

Na verdade, existe [toda uma questão do Stack Overflow](https://stackoverflow.com/questions/3895478/does-javascript-have-a-method-like-range-to-generate-a-range-within-the-supp) que tem mais de 20 implementações diferentes de um range. A que eu mais gosto é uma implementação simples e contida que usa as chaves de um array como valores:

```
[...Array(10).keys()]
// 0, 1, 2, 3, 4, 5, 6, 7, 8, 9
```

Eu inclusive [fiz um post há](https://www.instagram.com/p/Ch9cIUdL4Am/)um tempo mostrando como a gente pode implementar iteradores para criar uma função de range, que é **exatamente** como essa proposta é construída.

## Iterator.range

A ideia de como a proposta será implementada ainda está sob discussão, as duas opções seriam:

- Implementar o **método** range dentro da classe `Number`, ficando algo como `Number.range`
- Criar uma nova classe chamada `Interval` que conteria outros tipos de métodos além do range

Essa é uma [discussão aberta](https://github.com/tc39/proposal-Number.range/issues/22) que você, inclusive, pode participar!

> Eu, pessoalmente, não pendo muito para nenhum dos lados, mas dependendo do uso que os ranges devem ter eu diria que sou mais a favor do método do que da classe, pelo menos por agora.

Imaginando que a proposta original, que é utilizar um método na classe `Number`, esteja ganhando, a proposta vai adicionar uma função `range` que tem essa assinatura tanto em `Number` quanto em `BigInt`:

```
class Number {
  range(start: number, end: number, options: { step: number = 1, inclusive: boolean = false } | step: number = 1): RangeIterator;
}

class BigInt {
  range(start: bigint, end: bigint | Infinity | -Infinity, options: { step: bigint = 1n, inclusive: boolean = false } | step: bigint = 1n): RangeIterator;
}
```

Isso significa que poderemos fazer algo desse tipo:

```
for (const i of Number.range(1, 10)) {
  console.log(i); // => 1, 2, 3, 4, 5, 6, 7, 8, 9
}
```

Ou até mesmo simplificar um pouco fazendo um destructuring da propriedade:

```
const { range } = Number
console.log(...range(1, 10, 2))
```

Onde o terceiro parâmetro pode ser tanto o `step` quanto um objeto de opções que contém essas propriedades:

- `step`: Quantos números devemos pular por vez, esse pode ser um número negativo, portanto você pode criar ranges que começam, por exemplo, do 100 e vão até 0 com `range(100, 0, -1)`
- `inclusive`: é uma propriedade que define se o valor final está incluso na contagem, por exemplo, `range(100, 0, -1)` contaria de 100 até 1, excluindo o `0`, já `range(100, 0, {inclusive: true, step: -1})` iria contar de 100 até 0.

## Futuras implementações

Essa proposta funciona muito bem com outra proposta chamada [slice notation](https://github.com/tc39/proposal-slice-notation), que adiciona uma notação do tipo `[inicio:fim]` para o JavaScript. Na proposta um dos exemplos principais é lidar com arrays, por exemplo:

```
const arr = ['a', 'b', 'c', 'd'];

arr[1:3];
// → ['b', 'c']

arr.slice(1, 3);
// → ['b', 'c']
```

Ou seja, a ideia é substituir o uso do `slice` direto, porém, no caso dos ranges, poderíamos fazer algo assim:

```
const x = 1:3 // [1,2,3]
```

Que seria o mesmo que usar `range(1, 3, { inclusive:true })`. E essa parece ser uma proposta bastante interessante, principalmente se pudermos fazer algo assim:

```
for (let x in 1:100) {}
```

## Conclusão

Mesmo que a proposta seja recente e esteja em discussão, eu acredito que ela vai ser o suficiente para mudar a forma como a gente trabalha com JavaScript, pelo menos de uma forma sutil.

Se você quiser testar essa proposta por ai, o pacote [core-js](https://github.com/zloirock/core-js/#numberrange) contém polyfills para essas funções e basta você dar um `npm install core-js` no seu pacote, criando um arquivo como esse `index.mjs`:

```
import 'core-js/proposals/number-range.js'
const { range } = Number
console.log(...range(100, 0, -1))

```

Eu fortemente recomendo fazer seus testes e encontrar outros usos para o range. E também te convido a comentar lá na proposta com suas opiniões sobre como essa API deveria ser!

Curtiu essa ideia? Deixa um comentário aqui com seus usos do range e me chama nas minhas [redes sociais](https://lsantos.dev) que eu vou adorar falar sobre isso!