Translate

martes, 23 de diciembre de 2025

Métodos Monádicos en C++ — Parte 2


En la el post anterior vimos cómo transform, and_then y or_else permiten escribir código más expresivo con std::optional y std::expected.

Ahora vamos a ir un paso más allá: cómo componer funciones monádicas y diseñar código fluido sin excepciones.

El poder real de los métodos monádicos aparece cuando se encadenan varias transformaciones.

Veamos un ejemplo usando std::optional:


auto half = [](int x) -> std::optional<int> {

    return x % 2 == 0 ? x / 2 : std::nullopt;

};


auto addTen = [](int x) { return x + 10; };


std::optional<int> result =

    std::optional(8)

        .and_then(half)

        .transform(addTen); // ((8 / 2) + 10) = 14


Si en algún punto se devuelve std::nullopt, toda la cadena se corta automáticamente.


Con std::expected, el patrón es el mismo, pero ahora los errores son valores explícitos:


std::expected<int, std::string> parse(std::string s);

std::expected<int, std::string> divideByTwo(int x);


auto r = parse("42")

    .and_then(divideByTwo)

    .transform([](int n){ return n * 3; })

    .or_else([](auto err){

        std::cerr << "Error: " << err << "\\n";

        return std::expected<int, std::string>(0);

    });


Si cualquiera de las funciones falla, se propaga el error automáticamente.

No se necesitan try/catch ni comprobaciones manuales.

Si querés que tus funciones participen en estos encadenamientos, deben:

  • Retornar un std::optional<T> o std::expected<T, E>.
  • No lanzar excepciones.
  • No asumir que el valor siempre existe.


Ejemplo:


std::expected<int, std::string> toInt(std::string s) {

    try {

        return std::stoi(s);

    } catch (...) {

        return std::unexpected("invalid integer");

    }

}


Esta función ya puede encadenarse con .and_then() o .transform().

Los métodos monádicos de C++23 no solo son una mejora sintáctica, son una nueva forma de estructurar la lógica — más declarativa, más segura y más fácil de leer.

Y recuerda:

  • Usá transform para funciones simples (no cambian el contexto).
  • Usá and_then cuando la función devuelva otro optional o expected.
  • Usá or_else para recuperación o logging.
  • Evitá mezclar estos métodos con if/else sobre .has_value() — se pierde la gracia funcional.
  • Pensá tus funciones como operaciones puras.