diff options
author | Vincent Ambo <tazjin@gmail.com> | 2017-10-22T15·35+0200 |
---|---|---|
committer | Vincent Ambo <tazjin@gmail.com> | 2017-10-22T15·39+0200 |
commit | 4df6ba856ba293e15ca0be271dbb897a76bbbccc (patch) | |
tree | ffa54002d03ad75c92771c953adc5350248eaca7 /README.md | |
parent | 49a553c5c58c9e32ce1d1f15e37cb6ddd16afab6 (diff) |
docs: Add README with a bit of explanation
Diffstat (limited to 'README.md')
-rw-r--r-- | README.md | 52 |
1 files changed, 52 insertions, 0 deletions
diff --git a/README.md b/README.md new file mode 100644 index 000000000000..752390fa1442 --- /dev/null +++ b/README.md @@ -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) |