Introdução a programação funcional com TypeScript e JavaScript
Tags: typescript, webdev, tutorial, beginners
Published: 2022-07-21 02:22:11

## O que é programação funcional ?

Com o aumento da complexidade de programas e seus inúmeros estados, estamos voltando a um paradigma antigo: o Funcional. Muitos programadores já estão acostumados com o paradigma orientado a objetos e por isso, começarei dando um comparativo. Programação orientada a objetos possui muitos padrões e regras, mas podemos resumir da seguinte forma: *Programação orientada a objetos impõe disciplina sobre a transferência indireta do controle dos dados* e isso em comparação a programação funcional *Programação funcional impõe disciplina sobre a atribuição*. Essas duas frases dizem muito sobre os respectivos paradigma, que vamos nos aprofundar nesse blog post.

## O que eu ganho com isso ?

Ao saber um novo paradigma você ganha noas armas para resolver problemas antigos até mais facilmente que antes. vou mostrar um script "puro" em TypeScript e depois outro impuro em TypeScript e por fim um belo exemplo do mesmo exercicio em clojure.
vou colocar abaixo o código inteiro do script e vamos aos poucos analizando e entendendo o que tem acontecido

## O começo

```typescript
const customFunction = (
  value1: number,
  value2: number,
  funcEvaluater: string,
  textObj: { todayText: string; tomorrowText: string }
) => {
  function createdFunction(funcEvaluater) {
    return eval(funcEvaluater);
  }

  const currier =
    (textObj: { todayText: string; tomorrowText: string }) =>
    (val2: string) =>
    (val3: string) => {
      return textObj.todayText + val2 + textObj.tomorrowText + val3;
    };

  return [value1 + value2, createdFunction(funcEvaluater), currier(textObj)];
};

const [sum, evaluator, curryWhater] = customFunction(2, 3, '3 + 3', {
  todayText: 'Today is: ',
  tomorrowText: ' and tomorrow will be: ',
});

const getTodayWheterApi = (userLocation: string) => {
  // call api
  return 'Raining';
};
const getTomorrowWheterApi = (userLocation: string) => {
  // call api
  return 'Sunny';
};
// Chama a localização do user aqui
const currentLocation = 'userCurrentLocation';
appDiv.innerHTML = `
<h2>value: ${sum}</h2>
<h3>Eval: ${evaluator} </h3>
<h3>curry: ${curryWhater(getTodayWheterApi(currentLocation))(getTomorrowWheterApi(currentLocation))} </h3>`;
```

## Funções puras

A única forma perfeita de enpasulamento é funções. podemos ver em nossa função chamada customFunction 

```typescript
const customFunction = (
  value1: number,
  value2: number,
  funcEvaluater: string,
  textObj: { todayText: string; tomorrowText: string }
) => {
  function createdFunction(funcEvaluater) {
    return eval(funcEvaluater);
  }

  const currier =
    (textObj: { todayText: string; tomorrowText: string }) =>
    (val2: string) =>
    (val3: string) => {
      return textObj.todayText + val2 + textObj.tomorrowText + val3;
    };

  return [value1 + value2, createdFunction(funcEvaluater), currier(textObj)];
};
```

Tudo que você usa nessa função, você recebe como parametro, e ainda assim existe um retorno, logo você acaba por trabalhar, fazer algum calculo, chamada de api ou qualquer outro tratamento no fluxo de dados e por fim retorna o que você fez, nesse caso, recebemos 4 argumentos, 2 valores que serão somados e retornados por primeiro, uma função que será evaliada(não use eval em produção) e por fim, retorna também além do resultado do eval, o curry baseado em um objeto que foi passado como parametro, o curry em poucas palavras é uma função que gera outra função.

## Qual o resultado disso ?

Por ser uma função pura e ser facilmente digerida, devido ser um encapsulamento perfeito, fora dela, temos os seus resultados sendo usados.

```typescript
const [sum, evaluator, curryWhater] = customFunction(2, 3, '3 + 3', {
  todayText: 'Today is: ',
  tomorrowText: ' and tomorrow will be: ',
});
```

E esse resultado na interface do user se tornará isso daqui

```typeScript
const getTodayWheterApi = (userLocation: string) => {
  // call api
  return 'Raining';
};
const getTomorrowWheterApi = (userLocation: string) => {
  // call api
  return 'Sunny';
};
// Chama a localização do user aqui
const currentLocation = 'userCurrentLocation';
html do user
appDiv.innerHTML = `
<h2>value: ${sum}</h2>
<h3>Eval: ${evaluator} </h3>
<h3>curry: ${curryWhater(getTodayWheterApi(currentLocation))(getTomorrowWheterApi(currentLocation))} </h3>`;
```

o print abaixo mostra o resultado 

![HTML resultante](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/6t8niqsy7vv4svj3neo4.png)
 

Isso deixa facilmente ajustavel qualquer parte do código uma vez que cada passo, temos uma constante resultante de uma função.

### E na prática como que ficaria isso ?
 Podemos olhar o caso classico de um for loop, eu fiz o mesmo for loop duas vezes em typescript para mostrar uma versão mais moderna do antigo e em meu ver até mais bonita
```typescript

// for loop classico
for (let i = 0; i < 30; i++) {
  console.log(i * i);
}
// for loop moderno  -> seu array = Array.from(Array(30).keys())
for (const [index, value] of Array.from(Array(30).keys()).entries()) {
  console.log(value * value);
}
// exemplo prático do array moderno
const array = [1, 2, 3, 4, 5, 6, 7, 8];
for (const [index, value] of array.entries()) {
  console.log(value);
}

```

Básico não é ? é relaticamente simples e facil de ser entendido, mas ao mesmo tempo, me irrita no classico, o fato de termos uma variavél que será descartada depois.<br/>
Em Clojure temos a mesma solução desse problema, que ao meu ver extremamente lindo:

```clojure

;; resolver função que faz o quadrado dos primeiros 30 numeros inteiros
(defn create-n-list
  "creates a n list"
  [numbers]
  (take (+ numbers 1) (range)))

(defn first-n-multiples "recebe n numeros e retorna uma lista com seus multiplos"
  [numbers]
  (map * (create-n-list numbers) (create-n-list numbers)))

;; (first-n-multiples 30)
;;=> (0 1 4 9 16 25 36 49 64 81 100 121 144 169 196 225 256 289 324 361 400 441 484 529 576 625 676 729 784 841 900)

```
por mais que eu tenha criado duas funções existem maneiras de fazer via função anonima, porem dessa forma, fica bem explicito o que é buscado a ser feito. Essa lista que foi retornada poderá ser usada como uma constante e assim por diante.<br/>
Caso sinta alguma dificuldade lendo esse código em Clojure, me mande uma DM no twitter, ficarei extremamente feliz em lhe ajudar! Maior dificuldade de muitas pessoas com o clojure é sua notação infixa, como o exemplo de sua multiplicação sendo (* n n).
## Conclusão

Como conhecimento nunca é de mais, acredito que dar uma chance e tentar escrever códigos mais funcionais, com menos estados e mais funções e constantes, pode ser uma boa prática para o futuro num geral. Recomendo conhecer alguma variação de LISP e se apaixonar por como uma linguagem tão simples pode ser tão poderosa.