parent-no-raw-loops
Sean Parent Style Guide
Overview
Sean Parent, former Principal Scientist at Adobe, transformed how many think about C++ with his "C++ Seasoning" and "Better Code" talks. His central thesis: raw loops are assembly language for algorithms. If you're writing a loop, you're probably missing an algorithm.
Core Philosophy
"No raw loops."
"A goal of software engineering is to reduce code to its essence, to remove anything that doesn't contribute to the meaning."
Parent believes that code should be a direct expression of intent, and loops obscure intent by exposing mechanism.
Design Principles
-
No Raw Loops: Every loop is a missed opportunity to use (or create) a named algorithm.
-
Algorithms Express Intent:
std::find_ifsays "search"; a for-loop says "increment and compare." -
Composition Over Iteration: Build complex operations from simple, well-named pieces.
-
Seek the Essence: Remove everything that doesn't contribute to meaning.
When Writing Code
Always
- Use standard algorithms when they fit exactly
- Create named algorithms when standard ones don't fit
- Prefer algorithms that express the operation's semantic meaning
- Use range-based operations (C++20 ranges when available)
- Compose simple operations rather than write complex loops
- Name intermediate variables to document intent
Never
- Write raw
forloops when an algorithm exists - Nest loops when composition would work
- Inline complex logic that deserves a name
- Sacrifice clarity for cleverness
- Leave unnamed concepts in code
Prefer
std::transformover element-by-element loopsstd::accumulateover manual aggregationstd::partitionover manual reorderingstd::remove_if+ erase over manual deletion- Algorithm pipelines over nested loops
The Algorithm Catalog
Existence Queries
| Need | Algorithm |
|---|---|
| Does any element satisfy P? | std::any_of |
| Do all elements satisfy P? | std::all_of |
| Does no element satisfy P? | std::none_of |
| How many satisfy P? | std::count_if |
Finding
| Need | Algorithm |
|---|---|
| Find first matching P | std::find_if |
| Find first mismatch | std::mismatch |
| Find subsequence | std::search |
| Binary search | std::lower_bound, std::upper_bound |
Transforming
| Need | Algorithm |
|---|---|
| Apply f to each element | std::transform |
| Fill with value | std::fill |
| Generate values | std::generate |
| Copy with filter | std::copy_if |
Reordering
| Need | Algorithm |
|---|---|
| Sort | std::sort, std::stable_sort |
| Partition by P | std::partition, std::stable_partition |
| Rotate | std::rotate |
| Remove matching P | std::remove_if |
Code Patterns
Before and After: The Transformation
// RAW LOOP: What is this doing?
std::vector<int> result;
for (const auto& item : items) {
if (item.isValid()) {
result.push_back(item.getValue() * 2);
}
}
// ALGORITHM: Intent is clear
auto result = items
| std::views::filter(&Item::isValid)
| std::views::transform([](const Item& i) { return i.getValue() * 2; })
| std::ranges::to<std::vector>();
// Or without C++20 ranges:
std::vector<int> result;
std::transform(
items.begin(), items.end(),
std::back_inserter(result),
[](const Item& i) -> std::optional<int> {
return i.isValid() ? std::optional{i.getValue() * 2} : std::nullopt;
}
);
// (Then filter nullopt... or use a custom transform_if)
The Erase-Remove Idiom
// RAW LOOP: Error-prone, unclear intent
for (auto it = vec.begin(); it != vec.end(); ) {
if (shouldRemove(*it)) {
it = vec.erase(it); // O(n) each time!
} else {
++it;
}
}
// ALGORITHM: O(n) total, clear intent
vec.erase(
std::remove_if(vec.begin(), vec.end(), shouldRemove),
vec.end()
);
// C++20: Even clearer
std::erase_if(vec, shouldRemove);
Slide Algorithm (Parent's Signature)
// Move a range to a new position within a sequence
template<typename I> // I models RandomAccessIterator
auto slide(I first, I last, I pos) -> std::pair<I, I> {
if (pos < first) return { pos, std::rotate(pos, first, last) };
if (last < pos) return { std::rotate(first, last, pos), pos };
return { first, last };
}
// Usage: Move selected items to position
auto [new_first, new_last] = slide(
selection_begin, selection_end,
drop_position
);
Gather Algorithm
// Move all elements satisfying predicate to position
template<typename I, typename P>
auto gather(I first, I last, I pos, P pred) -> std::pair<I, I> {
return {
std::stable_partition(first, pos, std::not_fn(pred)),
std::stable_partition(pos, last, pred)
};
}
// Usage: Gather all selected items around cursor
auto [sel_first, sel_last] = gather(
items.begin(), items.end(),
cursor_position,
[](const Item& i) { return i.selected; }
);
Mental Model
Parent thinks of code as mathematical composition:
- Name the operation: What am I really doing?
- Find the algorithm: Does this operation have a name?
- Compose primitives: Can I build this from smaller operations?
- Factor out patterns: Is this useful elsewhere?
The Refactoring Test
When you see a loop, ask:
- Is this searching? →
find,search,any_of... - Is this transforming? →
transform,copy_if... - Is this reordering? →
sort,partition,rotate... - Is this aggregating? →
accumulate,reduce... - Is this comparing? →
equal,mismatch...
If none fit exactly, write and name a new algorithm.
More from copyleftdev/sk1llz
google-material-design
Design interfaces following Google's Material Design system, the unified visual language bridging digital and physical worlds. Emphasizes bold graphic design, intentional motion, adaptive layouts, and the material metaphor. Use when building modern, accessible, delightful user interfaces across platforms.
118renaissance-statistical-arbitrage
Build trading systems in the style of Renaissance Technologies, the most successful quantitative hedge fund in history. Emphasizes statistical arbitrage, signal processing, and rigorous scientific methodology. Use when developing alpha research, signal extraction, or systematic trading strategies.
104aqr-factor-investing
Build investment systems in the style of AQR Capital Management, the quantitative investment firm pioneering factor investing. Emphasizes academic rigor, transparent methodology, and systematic factor exposure. Use when building factor models, conducting asset pricing research, or designing systematic portfolios.
103minervini-swing-trading
Trade swing setups in the style of Mark Minervini, 3x US Investing Champion with 220%+ annual returns. Emphasizes SEPA methodology, trend templates, volatility contraction patterns (VCP), and strict risk management. Use when swing trading momentum stocks, identifying breakout setups, or building systematic trend-following strategies.
84de-shaw-computational-finance
Build trading systems in the style of D.E. Shaw, the pioneering computational finance firm. Emphasizes systematic strategies, rigorous quantitative research, and world-class technology infrastructure. Use when building research platforms, systematic trading strategies, or quantitative finance infrastructure.
63jump-trading-fpga-hft
Build trading systems in the style of Jump Trading, the high-frequency trading firm pioneering FPGA-based trading. Emphasizes hardware acceleration, network optimization, and nanosecond-level execution. Use when building FPGA trading systems, network-optimized infrastructure, or ultra-low-latency order execution.
29