Hola a todos, les recordamos que este mes en OTUS comenzará un nuevo set en el curso para desarrolladores de Golang . A pesar de cierto odio al artículo anterior sobre Golang, nuestro escritor independiente decidió correr el riesgo de continuar una serie de artículos dedicados a este idioma. Intentaremos atravesar este hielo delgado nuevamente, confiando en lo que parece confiar Golang: el paradigma funcional.
Le recordamos que este artículo es un tipo de material para "lectura extracurricular" y no está relacionado con el plan de estudios, que se puede encontrar aquí .Está claro que los programadores profesionales en otros idiomas llaman a Golang
la irritación es como un lenguaje compilado para adultos, pero el concepto de clases y herencia está ausente en principio (aunque OOP se implementa en un lenguaje, aunque de una manera bastante inusual, a través de un sistema de estructuras e interfaces). Sin embargo, hoy nos fijamos en las principales implementaciones de construcciones familiares en el paradigma funcional y tratamos de explicarlas y la sintaxis del lenguaje en sí.

Ahora hay mucha publicidad en torno al paradigma funcional (FP). Sin embargo, tampoco es una panacea para todos los problemas, y también tiene sus ventajas y desventajas.
Brevemente sobre qué es un paradigma funcional
El paradigma funcional llegó a la programación desde las matemáticas. Forma los siguientes requisitos para el programa:
- Sin cambios en los datos existentes.
- No hay estado oculto.
¿Qué nos da esto?Nuestras funciones funcionan sin efectos de terceros. En otras palabras, la función solo debería devolver un valor y no debería afectar a ningún dato externo.
Usando características puras. Aumentan la fiabilidad de las funciones de prueba sin importar los datos entrantes; en otras palabras, los programas se vuelven más confiables para las pruebas y sus resultados se vuelven más predecibles.
Entonces, ¿qué oportunidades tiene Golang para implementar un paradigma funcional?
Funciones de primera clase
Las funciones de primera clase están disponibles en muchos lenguajes de programación. El lector de este artículo probablemente ya conozca su concepto a partir de un JavaScript tan extendido, pero lo repetiré nuevamente. Las funciones de la primera clase (función de orden superior) son funciones que pueden devolver otra función como conocimiento, tomar una función como argumento y pasar el valor de la función a otra variable.
Acordemos desde el principio : para ahorrar espacio, eliminé las dos primeras líneas del código que se presenta aquí: 'paquete principal' e importar 'importar "fmt"'. Pero para ejecutar el código en su máquina, recuerde agregarlos).
func main() { var list = []int{15, 16, 45, 34}
De hecho, no es necesario inventar su propio
map
o
foreach
desde cero. Hay muchas bibliotecas que implementan esto, solo queda conectarlas. Por ejemplo,
este .
Cierres y funciones de curry
Hay cortocircuitos en muchos lenguajes de programación modernos. Los cierres son una función que se refiere a las variables de alcance libre de su función principal. El curry de funciones es un cambio de función de la forma
func(a,b,c)
a la forma
func(a)(b)(c)
.
Aquí hay un ejemplo de cierres y curry en Go:
Funciones puras
Como dijimos antes, las funciones puras son aquellas que devuelven valores que están asociados solo con argumentos que entran y no afectan el estado global.
Aquí hay un ejemplo de una función sucia fallida:
var arrToSave = map[string]int{}
Aquí, nuestra función debería aceptar trabajar de la manera más predecible posible:
func simpleSum(x, y int) int { return x + y } func main() { fmt.Printf("%v", dirtySum(13, 12))
"De alguna manera, la recursión entra en la barra, y nadie más entra en la barra"
De la colección de chistes sin gracia.Recursividad
En un paradigma funcional, se acostumbra dar preferencia a la recursividad, por la pureza y la transparencia, en lugar de usar una iteración simple
for
.
Aquí hay un ejemplo de cálculo factorial usando el paradigma imperativo y 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-- {
Ahora la función de recursión funciona de manera bastante ineficiente. Intentemos reescribirlo un poco para optimizar la velocidad de su cálculo:
func factTailRec(num int) int { return factorial(1, num)
Nuestra velocidad de cálculo factorial ha aumentado ligeramente. No voy a dar puntos de referencia).
Desafortunadamente, Go no implementa la optimización de recursión fuera de la caja, por lo que debe optimizar la cola de recursión usted mismo. Aunque, sin duda, se puede encontrar una biblioteca útil sobre este tema. Por ejemplo, hay una "Loadash para Golang" genial sobre este
tema .
Computación perezosa
En teoría de la programación, la computación diferida (también conocida como “computación diferida”) es el proceso de diferir la computación hasta que sea necesaria. Golang no es compatible con la computación diferida desde el primer momento, por lo que solo podemos simular esto:
func mult(x, y int) int { fmt.Println(" ") return x * x. } func divide(x, y int) int { fmt.Println(" ") return x / y
Muy a menudo, las expresiones perezosas "emuladas" no valen la pena porque complican demasiado el código, pero si sus funciones son bastante difíciles de administrar, entonces debería usar este método. Pero puede recurrir a otras soluciones, por ejemplo, a
estas .

Eso es todo. Solo recibimos una introducción al paradigma funcional en Golang. Desafortunadamente, parte de las posibilidades tuvieron que ser simuladas. Parte, las técnicas funcionales completamente desarrolladas, como las mónadas, no se incluyeron aquí, porque hay
muchos artículos sobre ellas en Go on the hub Todavía se puede mejorar mucho en el lenguaje en sí, por ejemplo, con la próxima versión grande (GO 2) se esperan genéricos en el idioma. Bueno, esperaremos y esperamos).