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

@ -2,24 +2,24 @@
## Discussion board
If you have a question or an idea regarding certain content but you want to have feedback of fellow community members
If you have a question or an idea regarding certain content but you want to have feedback of fellow community members
and you think it may not be appropriate to file an issue open a discussion in our [discussion board](https://github.com/rust-unofficial/patterns/discussions).
## Writing a new article
Before writing a new article please check our [issues](https://github.com/rust-unofficial/patterns/issues) and
Before writing a new article please check our [issues](https://github.com/rust-unofficial/patterns/issues) and
the [Pull Requests](https://github.com/rust-unofficial/patterns/pulls) if there are existing issues or someone
is working on that topic.
If you don't find an issue regarding your topic and you are sure it is not more feasible to open a thread in the [discussion board](https://github.com/rust-unofficial/patterns/discussions)
please open a new issue, so we can discuss about the ideas and future content of the article together and maybe
give some feedback/input on it.
give some feedback/input on it.
When writing a new article it's recommended to copy the [pattern template](https://github.com/rust-unofficial/patterns/blob/master/template.md) into the
appropriate directory and start editing it. You may not want to fill out every section and remove it or you might want to add extra sections.
Consider writing your article in a way that has a low barrier of entry so also [Rustlings](https://github.com/rust-lang/rustlings) can follow
and understand the thought process behind it. So we can encourage people to use these patterns early on.
and understand the thought process behind it. So we can encourage people to use these patterns early on.
We encourage you to write idiomatic Rust code that builds in the [playground](https://play.rust-lang.org/).
@ -35,7 +35,7 @@ Please make `Draft Pull requests` early so we can follow your progress and can g
"Release early and often!" also applies to pull requests!
Once your article has some visible work, create a `[WIP]` draft pull request and give it a description of what you did or want to do.
Early reviews of the community are not meant as an offense but to give feedback.
Early reviews of the community are not meant as an offense but to give feedback.
A good principle: "Work together, share ideas, teach others."

@ -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`.
@ -62,10 +57,9 @@ If you want to build it locally you can run one of these two commands in the roo
- `mdbook serve`
Serves the book at `http://localhost:3000` (port is changeable, take a look at the terminal output
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).

@ -3,33 +3,33 @@
- [Introduction](./intro.md)
- [Idioms](./idioms/index.md)
- [Use borrowed types for arguments](./idioms/coercion-arguments.md)
- [Concatenating Strings with `format!`](./idioms/concat-format.md)
- [Constructor](./idioms/ctor.md)
- [The `Default` Trait](./idioms/default.md)
- [Collections Are Smart Pointers](./idioms/deref.md)
- [Finalisation in Destructors](./idioms/dtor-finally.md)
- [`mem::replace(_)`](./idioms/mem-replace.md)
- [On-Stack Dynamic Dispatch](./idioms/on-stack-dyn-dispatch.md)
- [Iterating over an `Option`](./idioms/option-iter.md)
- [Pass Variables to Closure](./idioms/pass-var-to-closure.md)
- [Privacy For Extensibility](./idioms/priv-extend.md)
- [Easy doc initialization](./idioms/rustdoc-init.md)
- [Temporary mutability](./idioms/temporary-mutability.md)
- [Use borrowed types for arguments](./idioms/coercion-arguments.md)
- [Concatenating Strings with `format!`](./idioms/concat-format.md)
- [Constructor](./idioms/ctor.md)
- [The `Default` Trait](./idioms/default.md)
- [Collections Are Smart Pointers](./idioms/deref.md)
- [Finalisation in Destructors](./idioms/dtor-finally.md)
- [`mem::replace(_)`](./idioms/mem-replace.md)
- [On-Stack Dynamic Dispatch](./idioms/on-stack-dyn-dispatch.md)
- [Iterating over an `Option`](./idioms/option-iter.md)
- [Pass Variables to Closure](./idioms/pass-var-to-closure.md)
- [Privacy For Extensibility](./idioms/priv-extend.md)
- [Easy doc initialization](./idioms/rustdoc-init.md)
- [Temporary mutability](./idioms/temporary-mutability.md)
- [Design Patterns](./patterns/index.md)
- [Builder](./patterns/builder.md)
- [Compose Structs](./patterns/compose-structs.md)
- [Fold](./patterns/fold.md)
- [Newtype](./patterns/newtype.md)
- [RAII Guards](./patterns/RAII.md)
- [Prefer Small Crates](./patterns/small-crates.md)
- [Contain unsafety in small modules](./patterns/unsafe-mods.md)
- [Visitor](./patterns/visitor.md)
- [Builder](./patterns/builder.md)
- [Compose Structs](./patterns/compose-structs.md)
- [Fold](./patterns/fold.md)
- [Newtype](./patterns/newtype.md)
- [RAII Guards](./patterns/RAII.md)
- [Prefer Small Crates](./patterns/small-crates.md)
- [Contain unsafety in small modules](./patterns/unsafe-mods.md)
- [Visitor](./patterns/visitor.md)
- [Anti-patterns](./anti_patterns/index.md)
- [`#[deny(warnings)]`](./anti_patterns/deny-warnings.md)
- [Deref Polymorphism](./anti_patterns/deref.md)
- [`#[deny(warnings)]`](./anti_patterns/deny-warnings.md)
- [Deref Polymorphism](./anti_patterns/deref.md)
- [Functional Programming](./functional/index.md)

@ -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).

@ -1,6 +1,6 @@
# Anti-patterns
An [anti-pattern](https://en.wikipedia.org/wiki/Anti-pattern) is a solution to a "recurring problem that is usually ineffective and risks being highly counterproductive".
An [anti-pattern](https://en.wikipedia.org/wiki/Anti-pattern) is a solution to a "recurring problem that is usually ineffective and risks being highly counterproductive".
Just as valuable as knowing how to solve a problem, is knowing how _not_ to solve it.
Anti-patterns give us great counter-examples to consider relative to design patterns.
Anti-patterns are not confined to code. For example, a process can be an anti-pattern, too.

@ -8,7 +8,7 @@ In this way, the function will accept more input types.
This is not limited to slice-able or fat pointer types. In fact you should always prefer using the __borrowed type__ over __borrowing the owned type__. E.g., `&str` over `&String`, `&[T]` over `&Vec<T>`, or `&T` over `&Box<T>`.
Using borrowed types you can avoid layers of indirection for those instances where the owned type already provides a layer of indirection. For instance, a `String` has a layer of indirection, so a `&String` will have two layers of indrection.
We can avoid this by using `&str` instead, and letting `&String` coerce to a `&str` whenever the function is invoked.
We can avoid this by using `&str` instead, and letting `&String` coerce to a `&str` whenever the function is invoked.
## Example
@ -50,8 +50,8 @@ fn main() {
```
This works fine because we are passing a `&String` type as a parameter.
If we comment in the last two lines this example fails because a `&str` type will not coerce to a `&String` type.
We can fix this by simply modifying the type for our argument.
If we comment in the last two lines this example fails because a `&str` type will not coerce to a `&String` type.
We can fix this by simply modifying the type for our argument.
For instance, if we change our function declaration to:
@ -66,7 +66,7 @@ Ferris: false
Curious: true
```
But wait, that's not all! There is more to this story.
But wait, that's not all! There is more to this story.
It's likely that you may say to yourself: that doesn't matter, I will never be using a `&'static str` as an input anways (as we did when we used `"Ferris"`).
Even ignoring this special example, you may still find that using `&str` will give you more flexibility than using a `&String`.
@ -109,9 +109,10 @@ Running this example using our function declared with an argument type `&str` wi
curious has three consecutive vowels!
```
However, this example will not run when our function is declared with an argument type `&String`.
However, this example will not run when our function is declared with an argument type `&String`.
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
@ -34,4 +33,4 @@ impl<T> Vec<T> {
## See also
The [builder pattern](../patterns/builder.md) for constructing objects where there are multiple
configurations.
configurations.

@ -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

@ -83,7 +83,7 @@ Read`
## See also
* [Finalisation in destructors](dtor-finally.md) and
* [Finalisation in destructors](dtor-finally.md) and
[RAII guards](../patterns/RAII.md) can benefit from tight control over lifetimes.
* For conditionally filled `Option<&T>`s of (mutable) references, one can
initialize an `Option<T>` directly and use its [`.as_ref()`] method to get an

@ -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

@ -2,12 +2,13 @@
## Description
If a struct takes significant effort to initialize, when writing docs, it can be quicker to wrap your example with a
If a struct takes significant effort to initialize, when writing docs, it can be quicker to wrap your example with a
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.
Each of these methods should have examples.
For example:
@ -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
@ -77,7 +80,7 @@ So this pattern is most useful when need `no_run`. With this, you do not need to
## Discussion
If assertions are not required this pattern works well.
If assertions are not required this pattern works well.
If they are, an alternative can be to create a public method to create a dummy instance which is annotated with `#[doc(hidden)]` (so that users won't see it).
Then this method can be called inside of rustdoc because it is part of the crate's public API.

@ -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,19 +1,20 @@
# 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
There are many problems that share the same form. Due to the fact that Rust is not object-oriented design patterns vary with respect to other object-oriented programming languages. While the details are different, since they have the same form they can be solved using the same fundamental methods.
There are many problems that share the same form. Due to the fact that Rust is not object-oriented design patterns vary with respect to other object-oriented programming languages. While the details are different, since they have the same form they can be solved using the same fundamental methods.
[Design patterns](./patterns/index.md) are methods to solve common problems when writing software.
[Anti-patterns](./anti_patterns/index.md) are methods to solve these same common problems.
[Anti-patterns](./anti_patterns/index.md) are methods to solve these same common problems.
However, while design patterns give us benefits, anti-patterns create more problems.
[Idioms](./idioms/index.md) are guidelines to follow when coding. They are social norms of the community.
You can break them, but if you do you should have a good reason for it.
[Idioms](./idioms/index.md) are guidelines to follow when coding. They are social norms of the community.
You can break them, but if you do you should have a good reason for it.
TODO: Mention why Rust is a bit special - functional elements, type system, borrow checker

@ -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)
@ -120,7 +115,7 @@ works just as well.
RAII is a common pattern in C++: [cppreference.com](http://en.cppreference.com/w/cpp/language/raii),
[wikipedia][wikipedia].
[wikipedia]: https://en.wikipedia.org/wiki/Resource_Acquisition_Is_Initialization
[wikipedia]: https://en.wikipedia.org/wiki/Resource_Acquisition_Is_Initialization
[Style guide entry](https://doc.rust-lang.org/1.0.0/style/ownership/raii.html)
(currently just a placeholder).

@ -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

@ -1,6 +1,6 @@
# Design Patterns
[Design patterns](https://en.wikipedia.org/wiki/Software_design_pattern) are "general reusable solutions to a commonly occurring problem within a given context in software design".
[Design patterns](https://en.wikipedia.org/wiki/Software_design_pattern) are "general reusable solutions to a commonly occurring problem within a given context in software design".
Design patterns are a great way to describe some of the culture and 'tribal knowledge' of programming in a language.
Design patterns are very language-specific - what is a pattern in one language may be unnecessary in another due to a language feature, or impossible to express due to a missing feature.

@ -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

@ -1,10 +1,10 @@
# Newtype
What if in some cases we want a type to behave similar to another type or
enforce some behaviour at compile time where using only type aliases would
not be enough?
What if in some cases we want a type to behave similar to another type or
enforce some behaviour at compile time where using only type aliases would
not be enough?
For example, if we want to create a custom `Display` implementation for `String`
For example, if we want to create a custom `Display` implementation for `String`
due to security considerations (e.g. passwords).
For such cases we could use the `Newtype` pattern to provide __type safety__ and __encapsulation__.
@ -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

@ -6,7 +6,7 @@ We can use [design patterns](../patterns/index.md) to [DRY] up code and generali
> Shortcuts make for long days.
We can also use [idioms](../idioms/index.md) to structure our code in a way that is understandable.
We can also use [idioms](../idioms/index.md) to structure our code in a way that is understandable.
## Tests

@ -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