Higher Order Function

· 356 words · 2 minute read

A função de ordem superior (Higher Order Function) é um conceito fundamental na programação funcional, onde uma função pode receber outras funções como argumentos ou retornar funções como resultado. Esse padrão é amplamente utilizado em linguagens como JavaScript, Haskell e Lisp, permitindo a criação de código mais modular e reutilizável. Embora Go não seja uma linguagem puramente funcional, ela suporta funções de ordem superior.

Neste exemplo, a função setupTestServer() cria um servidor de teste HTTP e retorna uma URL, um roteador e uma função. Ela é considerada uma Higher Order Function porque retorna uma função que pode ser usada para fechar o servidor após os testes.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
func setupTestServer() (string, *http.ServeMux, func()) {
    router := http.NewServeMux()
    srv := httptest.NewServer(router)

    return srv.URL, router, func() { srv.Close() }
}

func TestSomething(t *testing.T) {
    url, router, close := setupTestServer()
    defer close()

    // ...
}

É muito comum em JS utilziar funções de ordem superior como callbacks, como no exemplo abaixo:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
function fetchData(url, callback) {
    fetch(url)
        .then(response => response.json())
        .then(data => callback(data))
        .catch(error => console.error('Error:', error));
}

function processData(data) {
    console.log('Processed Data:', data);
}

fetchData('https://api.example.com/data', processData);

Em Go também podemos criar funções que recebem outras funções como argumentos. Na função DoSomething() abaixo, passamos uma função como argumento para processar um mapa de parâmetros. Essa abordagem permite que a função seja flexível e reutilizável, aceitando diferentes implementações dessa função de carregamento de parâmetros.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
func LoadParams(params map[string]string) {
    for key, value := range params {
        fmt.Println("Key:", key, "Value:", value)
    }
}

func DoSomething(ctx context.Context, loader func(map[string]string)) {
    params := map[string]string{
        "param1": "value1",
        "param2": "value2",
    }

    loader(params)
}

func main() {
    DoSomething(context.Background(), LoadParams)
}

Imagina criar algo parecido com isso?

1
2
3
4
5
6
7
8
9
func Y(g func(any) any) func(any) any {
    return func(f any) func(any) any {
        return f.(func(any) any)(f).(func(any) any)
    }(func(f any) any {
        return g(func(x any) any{
        return f.(func(any) any)(f).(func(any) any)(x)
        })
    })
}