Skip to content

Commit 967c088

Browse files
committed
internal: document codebase stance on using functional combinators
1 parent e652545 commit 967c088

File tree

1 file changed

+25
-0
lines changed

1 file changed

+25
-0
lines changed

docs/dev/style.md

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -925,6 +925,31 @@ Don't use the `ref` keyword.
925925
Today, it is redundant.
926926
Between `ref` and mach ergonomics, the latter is more ergonomic in most cases, and is simpler (does not require a keyword).
927927

928+
## Functional Combinators
929+
930+
Use high order monadic combinators like `map`, `then`, only when they are a natural choice, don't bend the code to fit into some combinator.
931+
If writing a chain of combinators creates friction, replace them with control flow constructs: `for`, `if`, `match`.
932+
Mostly avoid `bool::then` and `Option::filter`.
933+
934+
```rust
935+
// GOOD
936+
if !x.cond() {
937+
return None;
938+
}
939+
Some(x)
940+
941+
// BAD
942+
Some(x).filter(|it| it.cond())
943+
```
944+
945+
This rule is more "soft" then others, and boils down mostly to taste.
946+
The guiding principle behind this rule is that code should be dense in computation, and sparse in the number of expressions per line.
947+
The second example contains *less* computation -- `filter` function is an indirection for `if`, it doesn't do any useful work by itself.
948+
At the same time, it is more crowded -- it takes more time to visually scan it.
949+
950+
**Rationale:** consistency, playing to language's strengths.
951+
Rust has first-class support for imperative control flow constructs like `for` and `if`, while functions are less first-class due to lack of universal function type, currying, and non-first-class effects (`?`, `.await`).
952+
928953
## Helper Functions
929954

930955
Avoid creating singe-use helper functions:

0 commit comments

Comments
 (0)