https://doc.rust-lang.org/beta/unstable-book/language-featur...
You only live once.
let x = (|| -> Result<i32, std::num::ParseIntError> {
Ok("1".parse::<i32>()?
+ "2".parse::<i32>()?
+ "3".parse::<i32>()?)
})();This works fine: https://play.rust-lang.org/?version=stable&mode=debug&editio...
The closest thing I can think of that will let you return a result from within a separate scope using a set of foo()? calls would be a lambda function that's called immediately, but that has its own problems when it comes to moving and it probably doesn't compile to very fast code either. Something like https://play.rust-lang.org/?version=stable&mode=debug&editio...
let foo: &[SomeType] = {
let mut foo = vec![];
// ... initialize foo ...
&foo
};
This doesn't work: the memory is owned by the Vec, whose lifetime is tied to the block, so the slice is invalid outside of that block. To be fair, it's probably best to just make foo a Vec, and turn it into a slice where needed.https://doc.rust-lang.org/beta/unstable-book/language-featur...
AFAIU it essentially creates a variable in inner scope but defers drop to the outer scope so that you can return the reference
- Drop does something, like close a file or release a lock, or
- x and y don't have Send and/or Sync, and you have an await point in the function or are doing multi-threaded stuff
This is why you should almost always use std::sync::Mutex rather than tokio::sync::Mutex. std's Mutex isn't Sync/Send, so the compiler will complain if you hold it across an await. Usually you don't want mutex's held across an await.
A lot of the time it looks like this:
let config = {
let config = get_config_bytes();
let mut config = Config::from(config);
config.do_something_mut();
config.do_another_mut();
config
};let mut data = foo(); data.mutate(); let data = data;
May be preferable for short snippets where adding braces, the yielded expression, and indentation is more noise than it's worth.
For example I feel this is right:
let x = x.parse()?;That last example is probably my biggest use of it because I hate having variables being unnecessarily mutable.
I typically use closures to do this in other languages, but the syntax is always so cumbersome. You get the "dog balls" that Douglas Crockford always called them:
``` const config = (() => { const raw_data = ...
...
return compiled;
})()'const result = config.whatever;
// carry on
return result; ```
Really wish block were expressions in more languages.
like
this {
const x = 5;
x + 5
}
// => 10
x
// => undefined
But I don’t see a way to get the result out of it. As soon as you try to use it in an expression, it will treat it as an object and fail to parse.(Not to be confused with do notation)
// double the value of `x` until it's at least 10
while { x = x * 2; x < 10 } {}
This isn't something that often will end up being more readable compared to another way to express it (e.g. an unconditional `loop` with a manual `break`, or refactoring the body into a separate function to be called once before entering the loop), but it's a fun trick to show people sometimes.Also in Kotlin, Scala, and nim.
break 'label value;
... is something to be used very sparingly. I reckon I write a new one about once a year.Very often if you think harder you realise you didn't want this, you should write say, a function (from which you can return) or actually you didn't want to break early at all. Not always, but often. If you write more "break 'label value" than just break then you are almost certainly Doing It Wrong™.