docs: Add README with a bit of explanation
This commit is contained in:
parent
49a553c5c5
commit
4df6ba856b
1 changed files with 52 additions and 0 deletions
52
README.md
Normal file
52
README.md
Normal file
|
@ -0,0 +1,52 @@
|
||||||
|
defer in Rust
|
||||||
|
=============
|
||||||
|
|
||||||
|
After a Hacker News discussion about implementing Go's `defer` keyword in C++,
|
||||||
|
I stumbled upon [this comment](https://news.ycombinator.com/item?id=15523589)
|
||||||
|
and more specifically this response to it by "Occivink":
|
||||||
|
|
||||||
|
> There's plenty of one-time cases where you don't want to declare an entire
|
||||||
|
> class but still enjoy scope-based functions.
|
||||||
|
|
||||||
|
Specificall the "don't want to declare an entire class" suggests that languages
|
||||||
|
like C++ have high friction for explaining your desired invariant (cleanup is
|
||||||
|
run when `$thing` is destroyed) to the compiler.
|
||||||
|
|
||||||
|
It seems like most languages either hand-wave this away (*cough* Java *cough*)
|
||||||
|
or use what seems like a workaround (`defer`).
|
||||||
|
|
||||||
|
Rust has the so-called `Drop` trait, which is a typeclass that contains a single
|
||||||
|
method with no return value that is run when a variable is dropped (i.e. goes out
|
||||||
|
of scope).
|
||||||
|
|
||||||
|
This works fine for most general cases - i.e. closing file handlers - but can
|
||||||
|
get complicated if other use-cases of `defer` are considered:
|
||||||
|
|
||||||
|
* returning an error-value by mutating a reference in the enclosing scope (oh boy)
|
||||||
|
* deferring a decision about when/whether to run cleanup to the caller
|
||||||
|
|
||||||
|
While thinking about how to do this with the `Drop` trait I realised that `defer`
|
||||||
|
can actually be trivially implemented in Rust, using `Drop`.
|
||||||
|
|
||||||
|
A simple implementation of `defer` can be seen in [defer.rs](examples/defer.rs),
|
||||||
|
an implementation using shared mutable state for error returns is in the file
|
||||||
|
[defer-with-error.rs](examples/defer-with-error.rs) and an implementation that
|
||||||
|
allows cleanup to be *cancelled* (don't _actually_ do this, it leaks a pointer)
|
||||||
|
is in [undefer.rs](examples/undefer.rs).
|
||||||
|
|
||||||
|
Whether any of this is actually useful is not up to me to decide. I haven't
|
||||||
|
actually had a real-life need for this.
|
||||||
|
|
||||||
|
You can run the examples with `cargo run --example defer`, etc.
|
||||||
|
|
||||||
|
## Notes
|
||||||
|
|
||||||
|
* `Drop` is not guaranteed to run in case of panics or program aborts, if you
|
||||||
|
need support for that check out [scopeguard](https://github.com/bluss/scopeguard)
|
||||||
|
|
||||||
|
|
||||||
|
## Further reading:
|
||||||
|
|
||||||
|
* [The Pain Of Real Linear Types in Rust](https://gankro.github.io/blah/linear-rust/)
|
||||||
|
* [Go's defer](https://tour.golang.org/flowcontrol/12)
|
||||||
|
* [Rust's Drop](https://doc.rust-lang.org/std/ops/trait.Drop.html)
|
Loading…
Reference in a new issue