> ## Content Index
> Fetch the complete content index at: https://jahans.blog/llms.txt
> Use this file to discover other available public pages before exploring further.

# On modern C++ and PLT
- URL: https://jahans.blog/on-modern-cpp-plt-part-1/
- Published: 2023-06-19T09:48:57.000Z
- Updated: 2025-07-29T03:40:11.000Z
- Author: Jahan Addison
- Tags: C++, PLT, language design, #Import 2026-09-13 01:33

Howdy, It's been a while :-). I've been largely immersed in modern C++ for the last few years—particularly C++20 and C++23, which have some groundbreaking changes if you haven't kept up.

I'll get to the point and let it speak for itself:

```C++
export module palindrome;
import <ranges>;
import <locale>;
export import <string_view>;
 
export bool constexpr is_palindrome(std::string_view str) {
    auto letters_only{str
        | std::views::filter([](char c) { return std::isalnum(c, std::locale{}); })
        | std::views::transform([](char c) { return std::tolower(c, std::locale{}); })
    };
    auto reversed{letters_only | std::views::reverse};
    
    return std::ranges::equal(letters_only, reversed);
}

```

Wow, right? That's a lot to unpack - especially if you haven't looked at C++ in a while. For starters, C++20 has a new modules feature akin to `import/export` in other languages. Second, C++20 has what's known as "ranges" that work on "views":

```c++
std::vector<std::string> strings{"string", "one", "two", "testing" };

auto sizes = strings
	| std::ranges::views::transform([](auto&& str) { return str.size(); })
	| std::ranges::views::filter([](auto size) { return size > 3; });

```

The astute programmer (or PLT enthusiast) will notice that `ranges` are higher-order operators and `views` are an algebraic type abstraction that satisfies constant time copy, move, and assignment operators.

This is profound because it's very close to monadic composition. [Not even Rust has higher-kinded polymorphism or free monadic composition](https://github.com/rust-lang/rfcs/issues/324?ref=jahans.blog).

This is just the beginning. C++23 takes the next big step — behold — the Maybe monad:

```C++
using namespace std::literals;

const std::vector<std::optional<std::string>> v
{
    "1234", "15 foo", "bar", "42", "5000000000", " 5", std::nullopt, "-43"
};

for (auto&& x : v | std::views::transform(
    [](auto&& o)
    {
        // debug print the content of input optional<string>
        std::cout << std::left << std::setw(13)
                  << std::quoted(o.value_or("nullopt")) << " -> ";

        return o
            // if optional is nullopt convert it to optional with "" string
            .or_else([]{ return std::optional{""s}; })
            // flatmap from strings to ints (making empty optionals where it fails)
            .and_then(to_int)
            // map int to int + 1
            .transform([](int n) { return n + 1; })
            // convert back to strings
            .transform([](int n) { return std::to_string(n); })
            // replace all empty optionals that were left by
            // and_then and ignored by transforms with "NaN"
            .value_or("NaN"s);
    }))
    std::cout << x << '\n';

```

Moreover, [flat\_map was added as a free standard header for container types](https://en.cppreference.com/w/cpp/header/flat%5Fmap?ref=jahans.blog). I can't put the language down right now.

As a personal researcher in PLT and computational linguistics, C++ is hitting all the right spots, and I expect this to continue to be the case for quite some time. There are enough toys in it to keep me busy for many years. On a side note, as far as PLT goes, I am not particularly interested in Rust: the syntax is offputting, and it can't do anything that grabs my attention.

I'd like to end this post with one last gem, C++23 has a new [class templatestd::expected](https://en.cppreference.com/w/cpp/utility/expected?ref=jahans.blog) \- functional programmers should quickly catch that this is the try monad for error handling. :-)

Catch you next time!