{"id":19198645,"url":"https://github.com/matheusfdosan/programacao-funcional","last_synced_at":"2026-02-28T03:48:01.117Z","repository":{"id":176091895,"uuid":"654976414","full_name":"matheusfdosan/programacao-funcional","owner":"matheusfdosan","description":"Uma explicação sobre Programação Funcional","archived":false,"fork":false,"pushed_at":"2023-06-22T17:49:20.000Z","size":10,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"main","last_synced_at":"2025-02-23T05:14:13.607Z","etag":null,"topics":["docs","functional-programming"],"latest_commit_sha":null,"homepage":"","language":null,"has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/matheusfdosan.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2023-06-17T13:59:03.000Z","updated_at":"2023-07-13T19:45:18.000Z","dependencies_parsed_at":null,"dependency_job_id":"0e9797b3-24b2-4566-a519-5ab10d8f0849","html_url":"https://github.com/matheusfdosan/programacao-funcional","commit_stats":null,"previous_names":["matheusfdosan/programacao-funcional"],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/matheusfdosan/programacao-funcional","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/matheusfdosan%2Fprogramacao-funcional","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/matheusfdosan%2Fprogramacao-funcional/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/matheusfdosan%2Fprogramacao-funcional/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/matheusfdosan%2Fprogramacao-funcional/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/matheusfdosan","download_url":"https://codeload.github.com/matheusfdosan/programacao-funcional/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/matheusfdosan%2Fprogramacao-funcional/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":29924700,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-02-27T19:37:42.220Z","status":"online","status_checked_at":"2026-02-28T02:00:07.010Z","response_time":90,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["docs","functional-programming"],"created_at":"2024-11-09T12:23:08.973Z","updated_at":"2026-02-28T03:48:01.099Z","avatar_url":"https://github.com/matheusfdosan.png","language":null,"funding_links":[],"categories":[],"sub_categories":[],"readme":"# Programação Funcional\n\nAssim como a Programação Orientada a Objetos, é um paradigma de programação, que é uma maneira de pensar e resolver problemas. O grande lance desse paradigma, são as **funções**, que guardam pequenas tarefas. Separamos problemas por tarefas pequenas. Sem modificar dados por fora dela, apenas dentro do escopo dela. Além de, serem bem pequenas e específicas no que fazer.\n\n## Por que programação funcional?\n\nServe para organizar linhas de raciocínio, quando entendemos uma nova maneira de abordar problemas, automaticamente, melhoramos o entendimento do problema e de encontro à solução. Além de, algumas tecnologias tem a programação funcional como requisito.\n\n## Características\n\nUm dado (ou mais), entrará na função e um dado novo sai dela, um dado modificado. Não altera os dados e não guarda o estado, que chamamos de `stateless`.\n\nAlgumas linguagens funcionais são:\n\n- JavaScript (multiparadigma)\n- PHP (multiparadigma)\n- Elixir\n- Haskell\n\nÉ uma linguagem de fácil manutenção, fácil para fazer testes, e também, deixa o código mais confiável.\n\n## Princípios\n\n- **Paradigmas**\n  - Programação Imperativa\n  - Programação Declarativa\n- **Dados**\n  - Imutabilidade\n  - Stateless\n- **Funções**\n  - Funções Independentes\n  - Funções Puras\n  - Higher-order Functions\n  - First-class Functions\n  - Composição de Funções\n\n## Programação Imperativa e Declarativa\n\n### Imperativo\n\nO modelo imperativo é como se fosse uma receita de bolo, nós instruímos ao computador passo a passo os comando que ele deve ensinar. Por exemplo:\n\n```js\n// Uma função que eleva o número ao quadrado\n// De forma imperativa: Como fazer\n\nlet number = 2\n\nfunction squared() {\n  return number * n\n}\n\nnumber = squared()\n```\n\nUma sequência de tarefas passo a passo. Linha a linha, fui falando como deve ser feito. Dar ordens.\n\n### Declarativo\n\nO modelo declarativo se concentra em descrever o que desejamos alcançar e deixar o computador se virar, ao invés de instruir especificamente ao computador o que queremos.\n\n```js\n// Uma função que eleva o número ao quadrado\n// De forma declarativa: O que fazer\nconst squared = (n) =\u003e n * n\n```\n\nUma função que eleva o número ao quadrado.\n\n\u003e Contudo, na programação imperativa damos todos os passos específicos, seguindo exatamente o que mandamos. Já na declarativa apenas dizemos onde queremos chegar e deixamos o computador se virar para dar o que queremos.\n\n## Imutabilidade\n\nUma variável não vai variar. Estamos falando sobre constantes, que sã variáveis que não podem ser reescritas. Por exemplo: temos uma bola azul, não posso mudar a cor da bola para amarela, então, criaremos outra bola da cor amarela.\n\n```js\nconst carrinho = {\n  produtos: 2,\n  preco_total: 30,\n}\n\ncarrinho.produtos = 3\n// isso não é possível de se fazer, o valor não pode ser alterado.\n\nconst novoCarrinho = { ...carrinho, produtos: 5 }\n// isso é possível, uma nova variável que pegar os valores de outra e muda certas coisas\n```\n\n## Stateless\n\nO conceito de **stateless** significa que algo não vai guardar o estado. No caso de funções, ela só vai conhecer os dados entregues a ela, e não vai pegar os dados de seu exterior. Pois, pode ser que a resposta dela varie.\n\n- **state** = estado\n- **less** = menos\n\nUm exemplo:\n\n```js\nlet number = 5\n\n// stateful function\nfunction squared() {\n  return number * number\n}\n\nnumber = squared() // 25\nnumber = squared() // 625\n\n// stateless function\nconst squared = (n) =\u003e n * n\n```\n\nVejamos que, em **stateful function**, a função utiliza o _number_ que está no seu exterior, contudo, no final `number = squared()`, a função vai sobrescrever o valor de _number_. Mas se chamarmos essa função novamente para sobrescrever _number_, o valor não será mais o mesmo. O que é um problema do **stateful function**\n\nJá no **stateless function**, a função não vai guardar nenhum valor, apenas receberá um valor e sempre o `n * n` será o resultado. Portanto, a função em si, não está guardando nenhum estado. A função não sabe o valor de `n`, só vai saber quando for passado.\n\n\u003e Então, o segredo é que, não posso depender de dados externos, não posso guardar dados na função, não posso alterar dados externos. Só vou trabalhar com dados entregues para a minha função.\n\n## Funções Independentes\n\nComo o próprio nome já diz, não pegará dados externos, apenas os dados passados para ela como argumento, deverá ter ao menos 1 argumento, e sempre retornará algo.\n\nNada do que acontecer dentro da função, afetará o mundo externo, pois os dados são imutáveis e não guardará estado.\n\nNão fazemos uso de loops, como for e while, mas se houver necessidade, utilizaremos a recursão para isso, que é a função chamando ela mesma.\n\nVeja um exemplo:\n\n```js\nconst random = (number, Math) =\u003e Math.floor(Math.random() * number)\n// Número aleatório\n// Sempre retorna algo\n\n// Encontrar o fatorial de um número\nconst factorial = (x) =\u003e {\n  // Se o número for igual a 0\n  if (x === 0) {\n    return 1\n  }\n\n  return x * factorial(x - 1) // Recursão\n}\n// Sempre retorna algo\n\nconst number = random(10, Math)\nconst factoredNumber = factorial(number)\n\nconsole.log(number + \"! =\", factoredNumber)\n```\n\nEm resumo, funções independentes trabalham com os dados passados como argumentos e não têm dependências externas, não afeta nada no código externo e não fazemos uso de loops, mas sim de recursão.\n\n## Funções Puras\n\nAs funções puras, assim como as independentes, não irão depender de nenhum dado externo, a não ser o que foi passado como argumento, além de, não afetar nada no código externo, sempre retornam o mesmo resultado para os mesmos argumentos, o que é conhecido como **determinismo**, e também são _stateless_ (não guardam estado). Veja:\n\n```js\n// Funções Puras\n// Exemplo 1: Depende apenas do dados passados como argumento\n\nfunction calculateCircumference(pi, radius) {\n  return pi * (radius + radius)\n}\n\ncalculateCircumference(Math.PI, 20) // 125.6637\n\n// Exemplo 2: Não altera dados externos, cria uma novo dado\n\nlet otherPerson = {\n  name: \"Larissa Camargo\",\n  age: \"Adulta\",\n}\n\nfunction changeName(person, newName) {\n  return { ...person, name: newName }\n}\n\nconst newOtherPerson = changeName(otherPerson, \"Larissa Mendonsa\")\n\nconsole.log(newOtherPerson)\n// { name: 'Larissa Mendonsa', age: 'Adulta' }\nconsole.log(otherPerson)\n// { name: 'Larissa Camargo', age: 'Adulta' }\n```\n\nEssas são as características de funções puras, logo, também existem as funções impuras, aquelas que dependem de dados externos, altera dados externos e guarda o estado:\n\n```js\n// Funções Impuras\n// Exemplo 1: Depende de dados externos\nfunction calculateCircumference(radius) {\n  return Math.PI * (radius + radius)\n}\n\n// Exemplo 2: Altera dados externos\nlet person = {\n  name: \"Rafael Almeida\",\n  age: \"Jovem\",\n}\n\nfunction changeName(name) {\n  person.name = name\n}\n```\n\n## First-class Function\n\nAs funções de primeira classe, podem estar em qualquer lugar, inclusive, como parâmetro de outras funções, tal função poderá ser entendida como uma variável.\n\n```js\nconst sayMyName = () =\u003e console.log(\"Matheus\")\n\nconst runMyFunction = (myFunc) =\u003e myFunc()\n// Pega a função e a executa (conceito de funções declarativas)\n\nrunMyFunction(sayMyName)\n// Poderá ser entendida como uma variável\n\nrunMyFunction(() =\u003e console.log(\"Hello, World!\"))\n// Passamos apenas funções\n\nconsole.log(runMyFunction(Math.random))\n```\n\n`Math.random` é uma função, mas passamos ela como se fosse uma variável, para `runMyFunction` executá-la dessa forma: `Math.random()`.\n\n## Higher-order Function (HOF)\n\nAs funções de ordem superior, ao contrário das _first-class function_, ao invés de serem recebidas como parâmetro de outras funções, as _Higher-order Function_ é a função que recebe as _first-class function_ como parâmetro, e também podem retornar outras funções como resultado.\n\n```js\nconst number = [2, 4, 6, 8]\n\nconst square = (n) =\u003e n ** 2\n// Pega o número e multiplica por ele mesmo\n\nconst squaredNumbers = number.map(square)\n// Cria um novo array, com todos os números elevados ao quadrado\n\nconsole.log(number) // [2, 4, 6, 8]\nconsole.log(squaredNumbers) // [ 4, 16, 36, 64 ]\n```\n\nNesse código, há um array de números, logo, pegamos esse array e criamos um novo, a partir do método `map()`, porém, esse método vai receber uma função que vai pegar cada número do array, e vai elevá-los ao quadrado (`const squaredNumbers = number.map(square)`).\n\n```js\nfunction avarage(...allGrades) {\n  return function (fn) {\n    console.log(fn(allGrades.length, allGrades))\n  }\n}\n\navarage(9, 7, 8, 10)((gradesLength, allGrades) =\u003e {\n  let gradesSum = 0\n  allGrades.forEach((grade) =\u003e {\n    gradesSum += grade\n  })\n  return gradesSum / gradesLength\n})\n```\n\nO `averageCalc` é uma função de ordem superior, pois tem a função `fn` como argumento e também retorna uma função.\n\nEm resumo, as _Higher-order functions_ recebem outras funções como argumentos ou retornam outras funções como resultado.\n\n## Currying\n\n**Currying** ou **aplicação parcial de função**, em homenagem a Haskell Curry, que fundamentou o conceito de paradigma funcional.\n\nExemplo de **currying**:\n\n```js\nconst sum = (n1) =\u003e (n2) =\u003e n1 + n2\nconsole.log(sum(5)(4)) // 9\n```\n\nBasicamente, é uma forma cuja função recebe apenas uma função. Portanto, para fazer uma função com dois ou mais parâmetros fixos, aninhamos funções e colocamos um parâmetro para cada, e, por fim, retornando elas mesmas, `const sum = (n1) =\u003e (n2) =\u003e ...`, dessa forma.\n\nE para usarmos essa função, em uma função normal colocamos `sum(5, 4)`, mas, no caso, usaremos `sum(5)(4)`, que significa que a primeira função recebe 5 como parâmetro `sum(5)`, e o segunda função, que não tem nome, recebe 4, `(4)`, junto à primeira função.\n\nContudo, na hora de executar essas funções, podemos adicionar um parâmetro por vez:\n\n```js\nconst curry = (func) =\u003e (a) =\u003e (b) =\u003e func(a, b)\n\nconst sum = (n1, n2) =\u003e n1 + n2\nconst useCurryToSum = curry(sum)\n\nconsole.log(useCurryToSum(5)(4))\n```\n\nExplicando:\n\n- `const curry = (func) =\u003e a =\u003e b =\u003e func(a, b)`: essa função tem a funcionalidade de executar uma outra função que utiliza os parâmetro a e b, para alguma tarefa, resumidamente.\n\n- `const sum = (n1, n2) =\u003e n1 + n2`: essa é a função que será passada ao `curry`.\n\n- `const useCurryToSum = curry(sum) `: estamos aplicando o currying na função `sum`. E agora`useCurryToSum` é uma função que pode ser chamada com dois conjuntos de parênteses separados, permitindo passar os argumentos um por vez.\n\n- `console.log(useCurryToSum(5)(4))`: dessa forma adicionamos os parâmetros 5 e 4, um por vez dentro da função useCurryToSum.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmatheusfdosan%2Fprogramacao-funcional","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fmatheusfdosan%2Fprogramacao-funcional","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmatheusfdosan%2Fprogramacao-funcional/lists"}