Apply markdownlint to project (#163)

pull/164/head
Takashi Idobe 3 years ago committed by GitHub
parent 345514a304
commit 5f1425d7ed
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

@ -0,0 +1,5 @@
---
MD004: false
MD010:
code_blocks: false
MD013: false

@ -3,35 +3,32 @@
An open source book about design patterns and idioms in the Rust programming
language that you can read [here](https://rust-unofficial.github.io/patterns/).
## TODOs
### Idioms
* TODO stability for extensibility
* TODO trait to separate visibility of methods from visibility of data (https://github.com/sfackler/rust-postgres/blob/v0.9.6/src/lib.rs#L1400)
* TODO trait to separate visibility of methods from visibility of data (<https://github.com/sfackler/rust-postgres/blob/v0.9.6/src/lib.rs#L1400>)
* TODO leak amplification ("Vec::drain sets the Vec's len to 0 prematurely so that mem::forgetting Drain "only" mem::forgets more stuff. instead of exposing uninitialized memory or having to update the len on every iteration")
* TODO interior mutability - UnsafeCell, Cell, RefCell
* TODO FFI usage (By being mindful of how to provide Rust libraries, and make use of existing libraries across the FFI, you can get more out of benefits Rust can bring)
### Design patterns
* TODO iterators (to safely avoid bounds checks)
* TODO closures and lifetimes (coupling to lifetime)
* TODO platform-specific sub-modules (https://github.com/rust-lang/rfcs/blob/master/text/0517-io-os-reform.md#platform-specific-opt-in)
* TODO platform-specific sub-modules (<https://github.com/rust-lang/rfcs/blob/master/text/0517-io-os-reform.md#platform-specific-opt-in>)
* TODO Module organisation (by looking at examples such as Rusts `libstd`, and how it integrated into the Rusts source code, lessons can be learned about ergonomic project management and API design. Closely assosciated with platform-specific sub-modules)
* [Entry API](patterns/entry.md) (Currently just a boilerplate)
* TODO extension traits
* TODO destructor bombs (ensure linear typing dynamically, e.g., https://github.com/Munksgaard/session-types/commit/0f25ccb7c3bc9f65fa8eaf538233e8fe344a189a)
* TODO convertible to Foo trait for more generic generics (e.g., http://static.rust-lang.org/doc/master/std/fs/struct.File.html#method.open)
* TODO destructor bombs (ensure linear typing dynamically, e.g., <https://github.com/Munksgaard/session-types/commit/0f25ccb7c3bc9f65fa8eaf538233e8fe344a189a>)
* TODO convertible to Foo trait for more generic generics (e.g., <http://static.rust-lang.org/doc/master/std/fs/struct.File.html#method.open>)
* [Late bound bounds](patterns/late-bounds.md) (Currently just a boilerplate)
* TODO 'shadow' borrowed version of struct - e.g., double buffering, Niko's parser generator
* TODO composition of structs to please the borrow checker
* TODO `Error` traits and `Result` forwarding
* TODO graphs
### Anti-patterns
* TODO thread + catch_panic for exceptions
@ -41,7 +38,6 @@ language that you can read [here](https://rust-unofficial.github.io/patterns/).
* TODO taking an enum rather than having multiple functions
* TODO `unwrap()`ing every `Result` instead of forwarding it
## Contributing
You are missing content in this repository that can be helpful for others and you are eager to explain it?
@ -49,7 +45,6 @@ Awesome! We are always happy about new contributions (e.g. elaboration or correc
We suggest reading our [Contribution guide](./CONTRIBUTING.md) to get more information on how it works.
## Building with mdbook
This book is built with [mdbook](https://rust-lang.github.io/mdBook/). You can install it by running `cargo install mdbook`.
@ -65,7 +60,6 @@ If you want to build it locally you can run one of these two commands in the roo
Serves the book at `http://localhost:3000` (port is changeable, take a look at the terminal output
to be sure) and reloads the browser when a change occurs.
## License
This content of this repository is licensed under **MPL-2.0**; see [LICENSE](./LICENSE).

@ -5,7 +5,6 @@
Abuse the `Deref` trait to emulate inheritance between structs, and thus reuse
methods.
## Example
Sometimes we want to emulate the following common pattern from OO languages such
@ -68,7 +67,6 @@ have two unrelated types. However, since the dot operator does implicit
dereferencing, it means that the method call will search for methods on `Foo` as
well as `Bar`.
## Advantages
You save a little boilerplate, e.g.,
@ -81,7 +79,6 @@ impl Bar {
}
```
## Disadvantages
Most importantly this is a surprising idiom - future programmers reading this in
@ -103,7 +100,6 @@ interfaces, class-based privacy, or other inheritance-related features. So, it
gives an experience that will be subtly surprising to programmers used to Java
inheritance, etc.
## Discussion
There is no one good alternative. Depending on the exact circumstances it might
@ -125,7 +121,6 @@ operator is a case where the ergonomics strongly favour an implicit mechanism,
but the intention is that this is limited to degrees of indirection, not
conversion between arbitrary types.
## See also
[Collections are smart pointers idiom](../idioms/deref.md).

@ -113,5 +113,6 @@ However, this example will not run when our function is declared with an argumen
This is because string slices are a `&str` and not a `&String` which would require an allocation to be converted to `&String` which is not implicit, whereas converting from `String` to `&str` is cheap and implicit.
## See also
- [Rust Language Reference on Type Coercions](https://doc.rust-lang.org/reference/type-coercions.html)
- For more discussion on how to handle `String` and `&str` see [this blog series (2015)](https://web.archive.org/web/20201112023149/https://hermanradtke.com/2015/05/03/string-vs-str-in-rust-functions.html) by Herman J. Radtke III.

@ -7,7 +7,6 @@ mutable `String`, or using its `+` operator. However, it is often more
convenient to use `format!`, especially where there is a mix of literal and
non-literal strings.
## Example
```rust
@ -23,7 +22,6 @@ fn say_hello(name: &str) -> String {
}
```
## Advantages
Using `format!` is usually the most succinct and readable way to combine strings.

@ -5,7 +5,6 @@
Rust does not have constructors as a language construct. Instead, the convention
is to use a static `new` method to create an object.
## Example
```rust,ignore

@ -5,7 +5,6 @@
Use the `Deref` trait to treat collections like smart pointers, offering owning
and borrowed views of data.
## Example
```rust,ignore
@ -40,7 +39,6 @@ must account for these semantics properly in order to give a good user
experience. When implementing a data structure which owns its data, offering a
borrowed view of that data allows for more flexible APIs.
## Advantages
Most methods can be implemented only for the borrowed view, they are then
@ -48,14 +46,12 @@ implicitly available for the owning view.
Gives clients a choice between borrowing or taking ownership of data.
## Disadvantages
Methods and traits only available via dereferencing are not taken into account
when bounds checking, so generic programming with data structures using this
pattern can get complex (see the `Borrow` and `AsRef` traits, etc.).
## Discussion
Smart pointers and collections are analogous: a smart pointer points to a single
@ -76,7 +72,6 @@ implement `Deref<Target=Bar<T>>` where `Bar` is a dynamically sized type and
Commonly, ordered collections will implement `Index` for `Range`s to provide
slicing syntax. The target will be the borrowed view.
## See also
[Deref polymorphism anti-pattern](../anti_patterns/deref.md).

@ -6,7 +6,6 @@ Rust does not provide the equivalent to `finally` blocks - code that will be
executed no matter how a function is exited. Instead an object's destructor can
be used to run code that must be run before exit.
## Example
```rust,ignore
@ -30,7 +29,6 @@ fn bar() -> Result<(), ()> {
}
```
## Motivation
If a function has multiple return points, then executing code on exit becomes
@ -41,13 +39,11 @@ an exception handling mechanism, but unlike Java (which has `finally`), there is
no way to schedule code to run in both the normal and exceptional cases.
Panicking will also exit a function early.
## Advantages
Code in destructors will (nearly) always be run - copes with panics, early
returns, etc.
## Disadvantages
It is not guaranteed that destructors will run. For example, if there is an
@ -62,7 +58,6 @@ debugging tricky.
Requiring an object and `Drop` impl just for finalisation is heavy on boilerplate.
## Discussion
There is some subtlety about how exactly to store the object used as a
@ -90,7 +85,6 @@ that desctructors are not absolutely guaranteed to run. It also means that you
must take extra care in your destructors not to panic, since it could leave
resources in an unexpected state.
## See also
[RAII](../patterns/RAII.md).

@ -84,7 +84,6 @@ Note, however, that if we are using an `Option` and want to replace its
value with a `None`, `Option`s `take()` method provides a shorter and
more idiomatic alternative.
## Advantages
Look ma, no allocation! Also you may feel like Indiana Jones while doing it.
@ -107,7 +106,6 @@ However, in Rust, we have to do a little more work to do this. An owned value
may only have one owner, so to take it out, we need to put something back in
like Indiana Jones, replacing the artifact with a bag of sand.
## See also
This gets rid of the [Clone to satisfy the borrow checker] antipattern in a

@ -8,7 +8,6 @@ give it copy of some data, pass it by reference, or perform some other transform
Use variable rebinding in separate scope for that.
## Example
Use
@ -45,7 +44,6 @@ let closure = move || {
};
```
## Advantages
Copied data are grouped together with closure definition, so their purpose is more clear
@ -53,8 +51,6 @@ and they will be dropped immediately even if they are not consumed by closure.
Closure uses same variable names as surrounding code whether data are copied or moved.
## Disadvantages
Additional indentation of closure body.

@ -5,7 +5,6 @@
Use a private field to ensure that a struct is extensible without breaking
stability guarantees.
## Example
```rust,ignore

@ -6,6 +6,7 @@ If a struct takes significant effort to initialize, when writing docs, it can be
function which takes the struct as an argument.
## Motivation
Sometimes there is a struct with multiple or complicated parameters and several methods.
Each of these methods should have examples.
@ -41,6 +42,7 @@ impl Connection {
```
## Example
Instead of typing all of this boiler plate to create an `Connection` and `Request` it is easier to just create a wrapping dummy function which takes them as arguments:
```rust,ignore
@ -64,6 +66,7 @@ impl Connection {
}
}
```
**Note** in the above example the line `assert!(response.is_ok());` will not actually run while testing because it is inside of a function which is never invoked.
## Advantages

@ -7,7 +7,6 @@ and never modified. The intention can be made explicit by redefining the mutable
It can be done either by processing data within nested block or by redefining variable.
## Example
Say, vector must be sorted before usage.
@ -34,14 +33,11 @@ let data = data;
// Here `data` is immutable.
```
## Advantages
Compiler ensures that you don't accidentally mutate data after some point.
## Disadvantages
Nested block requires additional indentation of block body.
One more line to return data from block or redefine variable.

@ -1,6 +1,7 @@
# Introduction
## Design patterns
When developing programs, we have to solve many problems. A program can be viewed as a solution to a problem. It can also be viewed as a collection of solutions to many different problems. All of these solutions work together to solve a bigger problem.
## Design patterns in Rust

@ -69,20 +69,17 @@ fn baz(x: Mutex<Foo>) {
}
```
## Motivation
Where a resource must be finalised after use, RAII can be used to do this
finalisation. If it is an error to access that resource after finalisation, then
this pattern can be used to prevent such errors.
## Advantages
Prevents errors where a resource is not finalised and where a resource is used
after finalisation.
## Discussion
RAII is a useful pattern for ensuring resources are properly deallocated or
@ -111,8 +108,6 @@ Note that implementing `Deref` is not a core part of this pattern, it only makes
using the guard object more ergonomic. Implementing a `get` method on the guard
works just as well.
## See also
[Finalisation in destructors idiom](../idioms/dtor-finally.md)

@ -50,13 +50,11 @@ fn builder_test() {
}
```
## Motivation
Useful when you would otherwise require many different constructors or where
construction has side effects.
## Advantages
Separates methods for building from other methods.
@ -65,13 +63,11 @@ Prevents proliferation of constructors
Can be used for one-liner initialisation as well as more complex construction.
## Disadvantages
More complex than creating a struct object directly, or a simple constructor
function.
## Discussion
This pattern is seen more frequently in Rust (and for simpler objects) than in

@ -14,7 +14,6 @@ behaviour.
This will often lead to a better design in other ways: applying this design
pattern often reveals smaller units of functionality.
## Example
Here is a contrived example of where the borrow checker foils us in our plan to
@ -68,19 +67,16 @@ fn baz(a: &mut A) {
}
```
## Motivation
TODO Why and where you should use the pattern
## Advantages
Lets you work around limitations in the borrow checker.
Often produces a better design.
## Disadvantages
Leads to more verbose code.
@ -89,7 +85,6 @@ Sometimes, the smaller structs are not good abstractions, and so we end up with
a worse design. That is probably a 'code smell', indicating that the program
should be refactored in some way.
## Discussion
This pattern is not required in languages that don't have a borrow checker, so

@ -4,7 +4,6 @@
A short, prose description of the pattern.
## Example
```rust
@ -12,27 +11,22 @@ A short, prose description of the pattern.
// liberally.
```
## Motivation
Why and where you should use the pattern
## Advantages
Good things about this pattern.
## Disadvantages
Bad things about this pattern. Possible contraindications.
## Discussion
TODO vs insert_or_update etc.
## See also
[RFC](https://github.com/rust-lang/rfcs/blob/master/text/0216-collection-views.md)

@ -70,7 +70,6 @@ A folder can also be defined to map one data structure to a different (but
usually similar) data structure. For example, we could fold an AST into a HIR
tree (HIR stands for high-level intermediate representation).
## Motivation
It is common to want to map a data structure by performing some operation on
@ -83,7 +82,6 @@ appropriate.
Like the visitor pattern, the fold pattern allows us to separate traversal of a
data structure from the operations performed to each node.
## Discussion
Mapping data structures in this fashion is common in functional languages. In OO
@ -108,7 +106,6 @@ the original data structure and we don't need to clone unchanged nodes. However,
they are less ergonomic to use and mean that the data structures cannot be
mutable.
## See also
Iterators have a `fold` method, however this folds a data structure into a

@ -4,7 +4,6 @@
TODO late binding of bounds for better APIs (i.e., Mutex's don't require Send)
## Example
```rust
@ -12,29 +11,24 @@ TODO late binding of bounds for better APIs (i.e., Mutex's don't require Send)
// liberally.
```
## Motivation
Why and where you should use the pattern
## Advantages
Good things about this pattern.
## Disadvantages
Bad things about this pattern. Possible contraindications.
## Discussion
A deeper discussion about this pattern. You might want to cover how this is done
in other languages, alternative approaches, why this is particularly nice in
Rust, etc.
## See also
Related patterns (link to the pattern file). Versions of this pattern in other

@ -52,7 +52,6 @@ fn main() {
}
```
## Motivation
The primary motivation for newtypes is abstraction. It allows you to share
@ -63,7 +62,6 @@ API, it allows you to change implementation backwards compatibly.
Newtypes can be used for distinguishing units, e.g., wrapping `f64` to give
distinguishable `Miles` and `Kms`.
## Advantages
The wrapped and wrapper types are not type compatible (as opposed to using
@ -83,7 +81,6 @@ You need a 'pass through' method for every method you want to expose on the
wrapped type, and an impl for every trait you want to also be implemented for
the wrapper type.
## Discussion
Newtypes are very common in Rust code. Abstraction or representing units are the
@ -99,7 +96,6 @@ pub struct Foo(Bar<T1, T2>);
Here, `Bar` might be some public, generic type and `T1` and `T2` are some internal types. Users of our module shouldn't know that we implement `Foo` by using a `Bar`, but what we're really hiding here is the types `T1` and `T2`, and how they are used with `Bar`.
## See also
- [Advanced Types in the book](https://doc.rust-lang.org/book/ch19-04-advanced-types.html?highlight=newtype#using-the-newtype-pattern-for-type-safety-and-abstraction)

@ -10,7 +10,6 @@ behaviour).
Furthermore, the visitor pattern allows separating the traversal of
a collection of objects from the operations performed on each object.
## Example
```rust,ignore
@ -70,7 +69,6 @@ impl Visitor<i64> for Interpreter {
One could implement further visitors, for example a type checker, without having
to modify the AST data.
## Motivation
The visitor pattern is useful anywhere that you want to apply an algorithm to
@ -78,7 +76,6 @@ heterogeneous data. If data is homogeneous, you can use an iterator-like pattern
Using a visitor object (rather than a functional approach) allows the visitor to
be stateful and thus communicate information between nodes.
## Discussion
It is common for the `visit_*` methods to return void (as opposed to in the

@ -4,7 +4,6 @@
A short, prose description of the pattern.
## Example
```rust
@ -21,29 +20,24 @@ please at least mark your example code with `ignore` as in here:
// liberally.
```
## Motivation
Why and where you should use the pattern
## Advantages
Good things about this pattern.
## Disadvantages
Bad things about this pattern. Possible contraindications.
## Discussion
A deeper discussion about this pattern. You might want to cover how this is done
in other languages, alternative approaches, why this is particularly nice in
Rust, etc.
## See also
Related patterns (link to the pattern file). Versions of this pattern in other

Loading…
Cancel
Save