Desvendando a Monad Result em JavaScript
Tags: javascript, webdev, functional, programming
Published: 2024-03-28 22:13:29

## Introdução:
Ao desenvolver em JavaScript, frequentemente nos deparamos com situações em que precisamos lidar com operações que podem ter sucesso ou falhar. Para facilitar esse cenário, podemos recorrer à monad `Result`, uma ferramenta poderosa que nos permite lidar com essas situações de forma elegante e segura. Neste artigo, vamos explorar como criar e usar a classe `Result` em JavaScript, inspirada no `Result` do Rust, e entender como ela se encaixa no conceito de monad.

## O que é a Monad Result?
A monad `Result` encapsula um valor que pode representar um resultado bem-sucedido ou um erro. É como uma caixinha que nos permite tratar operações que podem falhar de forma mais estruturada e previsível. Se você já está familiarizado com o `Result` em Rust, vai perceber que a ideia é bem similar.

## Criando a Classe Result em JavaScript:
Vamos dar uma olhada na implementação básica da classe `Result` em JavaScript:

```javascript
class Result {
    constructor(value, error) {
        this.value = value;
        this.error = error;
    }

    static Ok(value) {
        return new Result(value, null);
    }

    static Err(error) {
        return new Result(null, error);
    }

    map(fn) {
        return this.error ? this : new Result(fn(this.value), null);
    }

    andThen(fn) {
        return this.error ? this : fn(this.value);
    }

    catch(fn) {
        return this.error ? fn(this.error) : this;
    }

    unwrap() {
        if (this.error) {
            throw new Error(this.error);
        }
        return this.value;
    }
}

// Definindo uma função para dividir dois números
function dividir(a, b) {
    // Verificando se o divisor é zero
    if (b === 0) {
        // Se for, retornamos um Result.Err com uma mensagem de erro
        return Result.Err("Não é possível dividir por zero.");
    } else {
        // Caso contrário, retornamos um Result.Ok com o resultado da divisão
        return Result.Ok(a / b);
    }
}

// Exemplo de uso da função dividir
const resultadoDivisao = dividir(10, 2)
    .map(resultado => resultado * 3) // Multiplicando o resultado por 3
    .andThen(resultado => Result.Ok(resultado + 5)) // Adicionando 5 ao resultado
    .unwrap(); // Desembrulhando o valor final

console.log(resultadoDivisao); // Resultado = 20

// Tentativa de dividir por zero, erro propagado
const resultadoVoid = dividir(10, 0)
    .map(resultado => resultado * 3) // Não será executado devido ao erro
    .andThen(resultado => Result.Ok(resultado + 5)) // Não será executado devido ao erro

// Como não foi feito unwrap, o erro não foi tratado e permanece no objeto Result.
console.log(resultadoVoid) // Result { value: null, error: 'Não é possível dividir por zero.' }

// Tentativa de dividir por zero, erro propagado e tratado com try-catch
try {
    dividir(10, 0)
        .map(resultado => resultado * 3) // Não será executado devido ao erro
        .andThen(resultado => Result.Ok(resultado + 5)) // Não será executado devido ao erro
        .unwrap();
} catch (error) {
    console.log(error.message); // A mensagem de erro é capturada e exibida: "Não é possível dividir por zero."
}

// Tentativa de dividir por zero, erro capturado e manipulado
const resultadoDivisaoPorZero = dividir(10, 0)
    .map(resultado => resultado * 3) // Não será executado devido ao erro
    .andThen(resultado => Result.Ok(resultado + 5)) // Não será executado devido ao erro
    .catch((e) => Result.Err(`Ocorreu um erro: ${e}`)); // O erro é capturado e uma mensagem personalizada é retornada

console.log(resultadoDivisaoPorZero); // Result { value: null, error: 'Ocorreu um erro: Não é possível dividir por zero.' }
```

## Conclusão:
A monad `Result` em JavaScript é uma ferramenta valiosa para lidar com situações de sucesso ou falha de forma estruturada e controlada. Ao entender como criar e usar essa classe, podemos escrever código mais robusto e previsível em nossos projetos.

Se você quiser saber mais sobre monads e programação funcional, recomendo dar uma olhada nestes links:
- https://www.treinaweb.com.br/blog/conceitos-de-linguagens-funcionais-uma-breve-introducao-aos-monads/
- https://medium.com/tableless/programa%C3%A7%C3%A3o-funcional-avan%C3%A7ada-monads-em-javascript-862e8588fcdf