Cuando pensamos en C++, normalmente pensamos en for, iteradores y algoritmos como std::sort o std::find.
Pero C++ moderno incorporó una forma diferente de trabajar con colecciones: Ranges y Views.
Veamos un ejemplo:
#include <ranges>
#include <vector>
#include <iostream>
int main() {
std::vector<int> numbers = {1, 2, 3, 4, 5};
auto result = numbers
| std::views::filter([](int x) {
return x % 2 == 0;
})
| std::views::transform([](int x) {
return x * 10;
});
for (auto value : result) {
std::cout << value << " ";
}
}
Resultado: 20 40
El código se puede leer como un pipeline:
[1, 2, 3, 4, 5]
↓
filter(x es par)
↓
[2, 4]
↓
transform(x * 10)
↓
[20, 40]
¿Qué es un Range?
Un Range es una abstracción que representa una secuencia de elementos.
Por ejemplo:
std::vector<int>
puede ser un Range.
También:
std::list<int>
std::array<int, 10>
La idea de Ranges es permitir trabajar con diferentes estructuras utilizando una interfaz común.
En lugar de pensar vector o list podemos pensar en secuencia de elementos
¿Qué es una View?
Una View es una forma de ver o transformar un Range sin necesariamente crear una nueva colección.
Por ejemplo:
auto evenNumbers =
numbers
| std::views::filter([](int x) {
return x % 2 == 0;
});
Podemos pensar que evenNumbers representa: [2, 4]
Pero no necesariamente se creó un nuevo std::vector.
En cambio, tenemos una vista sobre los datos originales.
Esto nos lleva a una característica muy importante: Lazy evaluation
Las Views normalmente trabajan de forma lazy.
Esto significa que las transformaciones no se ejecutan necesariamente en el momento en que creamos el pipeline.
Por ejemplo:
auto result = numbers
| std::views::filter(isEven)
| std::views::transform(multiplyByTen);
En este punto estamos definiendo cómo se van a transformar los datos.
La evaluación ocurre cuando recorremos el resultado:
for (auto value : result) {
std::cout << value << " ";
}
Esto puede evitar crear colecciones intermedias.
Sin Views podríamos escribir:
std::vector<int> evenNumbers;
for (auto value : numbers) {
if (value % 2 == 0) {
evenNumbers.push_back(value);
}
}
std::vector<int> result;
for (auto value : evenNumbers) {
result.push_back(value * 10);
}
Con Ranges:
auto result = numbers
| std::views::filter([](int x) {
return x % 2 == 0;
})
| std::views::transform([](int x) {
return x * 10;
});
El código expresa directamente la intención: filtrar → transformar
¿Es programación funcional?
C++ sigue siendo C++.
Pero Ranges y Views incorporan ideas que resultarán familiares para quienes trabajan con programación funcional:
filter
map
pipelines
lazy evaluation
Por ejemplo: std::views::filter(...)
es similar a: filter
Y: std::views::transform(...)
es similar a: map
También podemos combinar operaciones:
numbers
| std::views::filter(...)
| std::views::transform(...)
| std::views::take(10);
El resultado es un pipeline de transformaciones.
Pero con C++20 y C++23, conceptos como pipelines, transformaciones y lazy evaluation forman parte del C++ moderno.

No hay comentarios.:
Publicar un comentario