Olá pessoal, lembramos que este mês no OTUS um novo conjunto será iniciado no curso Golang Developer . Apesar do ódio ao artigo anterior sobre Golang, nosso escritor freelancer decidiu correr o risco de continuar uma série de artigos dedicados a esse idioma. Vamos tentar passar por esse gelo fino novamente, contando com o que Golang parece confiar - o paradigma funcional.
Lembramos que este artigo é um tipo de material para "leitura extracurricular" e não está relacionado ao programa do curso, que pode ser encontrado aqui .É claro que programadores profissionais em outros idiomas Golang chama
irritação é como uma linguagem compilada para adultos, mas o conceito de classes e herança está ausente em princípio (embora o OOP seja implementado em uma linguagem, embora de maneira bastante incomum, através de um sistema de estruturas e interfaces). No entanto, hoje analisamos as principais implementações de construções familiares no paradigma funcional e tentamos explicar elas e a própria sintaxe da linguagem.

Agora, há muito hype em torno do paradigma funcional (FP). No entanto, também não é uma panacéia para todos os problemas, e também tem seus prós e contras.
Brevemente sobre o que é um paradigma funcional
O paradigma funcional veio para a programação da matemática. Ele forma os seguintes requisitos para o programa:
- Nenhuma alteração nos dados existentes.
- Não há estado oculto.
O que isso nos dá?Nossas funções funcionam sem efeitos de terceiros. Em outras palavras, a função deve retornar apenas um valor e não deve afetar nenhum dado externo.
Usando recursos puros. Eles aumentam a confiabilidade das funções de reteste, independentemente dos dados recebidos - em outras palavras, os programas se tornam mais confiáveis para testes e seus resultados se tornam mais previsíveis.
Então, quais são as possibilidades da Golang para implementar o paradigma funcional:
Funções de primeira classe
Funções de primeira classe estão disponíveis em várias linguagens de programação. O leitor deste artigo provavelmente já conhece seu conceito a partir de um JavaScript tão difundido, mas vou repetir novamente. As funções da primeira classe (função de alta ordem) são funções que podem retornar outra função como conhecimento, assumir uma função como argumento e passar o valor da função para outra variável.
Vamos concordar desde o início : para economizar espaço, joguei as duas primeiras linhas do código que é apresentado aqui: 'package main' e import 'import "fmt"'. Mas, para executar o código em sua máquina, lembre-se de adicioná-los).
func main() { var list = []int{15, 16, 45, 34}
De fato, não é necessário inventar seu próprio
map
ou
foreach
do zero. Existem muitas bibliotecas que implementam isso, resta apenas conectá-las. Por exemplo,
este .
Fechos e funções de curry
Existem curtos-circuitos em muitas linguagens de programação modernas. Encerramentos são uma função que se refere às variáveis de escopo livre de sua função pai. Função currying é uma mudança de função da forma
func(a,b,c)
para a forma
func(a)(b)(c)
.
Aqui está um exemplo de encerramentos e currying no Go:
Funções puras
Como dissemos antes, funções puras são aquelas que retornam valores associados apenas a argumentos que entram e não afetam o estado global.
Aqui está um exemplo de uma função suja com falha:
var arrToSave = map[string]int{}
Aqui, nossa função deve aceitar trabalhar da maneira mais previsível possível:
func simpleSum(x, y int) int { return x + y } func main() { fmt.Printf("%v", dirtySum(13, 12))
“De alguma forma, a recursão entra no bar e ninguém mais entra no bar”
Da coleção de piadas sem graça.Recursão
Em um paradigma funcional, é habitual dar preferência à recursão - por pureza e transparência, em vez de usar iteração simples por meio
for
.
Aqui está um exemplo de cálculo de fatorial usando o paradigma imperativo e declarativo:
func funcFactorial(num int) int { if num == 0 { return 1 } return num * funcFactorial(num-1) } func imperativeFactorial(num int) int { var result int = 1 for ; num > 0; num-- {
Agora, a função de recursão funciona de maneira bastante ineficiente. Vamos tentar reescrevê-lo um pouco para otimizar a velocidade de seu cálculo:
func factTailRec(num int) int { return factorial(1, num)
Nossa velocidade de computação fatorial aumentou um pouco. Não darei benchmarks).
Infelizmente, o Go não implementa a otimização de recursão pronta para uso, portanto, você deve otimizar a cauda da recursão. Embora, sem dúvida, uma biblioteca útil sobre esse tópico possa certamente ser encontrada. Por exemplo, existe um "Loadash for Golang" interessante sobre esse
tópico .
Computação preguiçosa
Na teoria da programação, a computação lenta (também conhecida como “computação diferida”) é o processo de diferir a computação até que seja necessária. Golang não tem suporte para computação lenta imediatamente, então podemos simular isso:
func mult(x, y int) int { fmt.Println(" ") return x * x. } func divide(x, y int) int { fmt.Println(" ") return x / y
Na maioria das vezes, expressões preguiçosas “emuladas” não valem a pena, porque complicam demais o código, mas se suas funções são bastante difíceis de gerenciar, você deve usar esse método. Mas você pode recorrer a outras soluções, por exemplo, para
essas .

Só isso. Nós apenas tivemos uma introdução ao paradigma funcional em Golang. Infelizmente, parte das possibilidades teve que ser simulada. Parte, técnicas funcionais totalmente desenvolvidas, como mônadas, não foram incluídas aqui, porque há
muitos artigos sobre eles no Go on the hub Muito ainda pode ser aprimorado no próprio idioma, por exemplo, com a próxima versão grande (GO 2), os genéricos devem aparecer no idioma. Bem, vamos esperar e esperar).