| ▲ | mojuba 4 hours ago |
| I like how Swift solved this: there's a more universal `defer { ... }` block that's executed at the end of a given scope no matter what, and after the `return` statement is evaluated if it's a function scope. As such it has multiple uses, not just for `try ... finally`. |
|
| ▲ | Someone an hour ago | parent | next [-] |
| I think Swift’s defer (https://docs.swift.org/swift-book/documentation/the-swift-pr...) was inspired by/copied from go (https://go.dev/tour/flowcontrol/12), but they may have taken it from an even earlier language that I’m not aware of. Defer has two advantages over try…finally: firstly, it doesn’t introduce a nesting level. Secondly, if you write foo
defer revert_foo
, when scanning the code, it’s easier to verify that you didn’t forget the revert_foo part than when there are many lines between foo and the finally block that calls revert_foo.A disadvantage is that defer breaks the “statements are logically executed in source code order” convention. I think that’s more than worth it, though. |
| |
| ▲ | mojuba an hour ago | parent [-] | | Yeah, it's especially handy in UI code where you can have asynchronous operations but want to have a clear start/end indication in the UI: busy = true
Task {
defer { busy = false }
// do async stuff, possibly throwing exceptions and whatnot
}
|
|
|
| ▲ | dwattttt 3 hours ago | parent | prev | next [-] |
| I was contemplating what it would look like to provide this with a macro in Rust, and of course someone has already done it. It's syntactic sugar for the destructor/RAII approach. https://docs.rs/defer-rs/latest/defer_rs/ |
| |
| ▲ | 2 hours ago | parent | next [-] | | [deleted] | |
| ▲ | mojuba 2 hours ago | parent | prev [-] | | I don't know Rust but, can this `defer` evaluate after the `return` statement is evaluated like in Swift? Because in Swift you can do this: func atomic_get_and_inc() -> Int {
sem.wait()
defer {
value += 1
sem.signal()
}
return value
}
| | |
| ▲ | kibwen an hour ago | parent | next [-] | | It's easy to demonstrate that destructors run after evaluating `return` in Rust: struct PrintOnDrop;
impl Drop for PrintOnDrop {
fn drop(&mut self) {
println!("dropped");
}
}
fn main() {
let p = PrintOnDrop;
return println!("returning");
}
But the idea of altering the return value of a function from within a `defer` block after a `return` is evaluated is zany. Please never do that, in any language. | |
| ▲ | ninkendo an hour ago | parent | prev [-] | | It gets even better in swift, because you can put the return statement in the defer, creating a sort of named return value: func getInt() -> Int {
let i: Int // declared but not
// defined yet!
defer { return i }
// all code paths must define i
// exactly once, or it’s a compiler
// error
if foo() {
i = 0
} else {
i = 1
}
doOtherStuff()
}
| | |
| ▲ | coldpie a minute ago | parent | next [-] | | I would scream if I saw this in an actual codebase. | |
| ▲ | mojuba an hour ago | parent | prev [-] | | Huh, I didn't know about `return` in `defer`, but is it really useful? |
|
|
|
|
| ▲ | troglo-byte 3 hours ago | parent | prev [-] |
| #include <iostream>
#define RemParens_(VA) RemParens__(VA)
#define RemParens__(VA) RemParens___ VA
#define RemParens___(...) __VA_ARGS__
#define DoConcat_(A,B) DoConcat__(A,B)
#define DoConcat__(A,B) A##B
#define defer(BODY) struct DoConcat_(Defer,__LINE__) { ~DoConcat_(Defer,__LINE__)() { RemParens_(BODY) } } DoConcat_(_deferrer,__LINE__)
int main() {
{
defer(( std::cout << "Hello World" << std::endl; ));
std::cout << "This goes first" << std::endl;
}
}
|
| |
| ▲ | rezonant 2 hours ago | parent | next [-] | | Why would that be preferable to just using an RAII style scope_exit with a lambda | | |
| ▲ | troglo-byte 2 hours ago | parent [-] | | Meh, I was going to use the preprocessor for __LINE__ anyways (to avoid requiring a variable name) so I just made it an "old school lambda." Besides, scope_exit is in C++23 which is still opt-in in most cases. |
| |
| ▲ | chuckadams an hour ago | parent | prev | next [-] | | "We have syntax macros at home" | |
| ▲ | 2 hours ago | parent | prev [-] | | [deleted] |
|