logoalt Hacker News

Joker_vDtoday at 1:52 PM3 repliesview on HN

Every time I see "use ranges and algorithms!" examples, I am baffled that apparently, I am supposed to find

    inline double algorithm_call(std::span<double const> xs) noexcept {
        return std::accumulate(
            xs.begin(),
            xs.end(),
            0.0,
            [](double acc, double volts) {
                auto mv  = calibrated_mv(volts);
                auto err = residual(mv);
                return weighted_square(err) + acc;
        });
    }
more readable, concise, and easier on my eyes than

    inline double raw_loop(std::span<double const> xs) noexcept {
        double sum = 0.0;

        for (double volts : xs) {
            auto mv  = calibrated_mv(volts);
            auto err = residual(mv);
            sum += weighted_square(err);
        }

        return sum;
    }
Sure, there are some algorithms in <algorithms> that I'm rather not reimplement myself, but this one is not it.

Replies

Erlangentoday at 4:19 PM

You said "ranges and algorithms", but you didn't copy the third function which actually uses <range> library.

inline double ranges_pipeline(std::span<double const> xs) noexcept { auto costs = xs | std::views::transform(calibrated_mv) | std::views::transform(residual) | std::views::transform(weighted_square);

  return std::ranges::fold_left(costs, 0.0, std::plus<double>{});
}

It's still a bit verbose, because C++ doesn't allow universal function call syntax. It will be even more concise in other languages like D.

show 1 reply
rzzzttoday at 2:07 PM

The first form is easier to send to 32 beefy cores or 1024 small CPUs or a Beowulf cluster or a GPU or people sitting in a room.

show 3 replies
fookertoday at 3:57 PM

Great, now use some functions. From the library or your own, and see this complexity become manageable.

That's what abstraction is about.