I use this all the time. It's features like these that sell Rust for me honestly; even if you wrapped your whole program in `unsafe` it would still be a massively better language than C++ or C.
Many languages use this idiom. Some popular ones even. So while it's good that Rust joined them, it's hardly a differentiator.
Rust's Block Pattern
91–100 of 121 posts
Re: Rust's Block Pattern
#92We do this via run in TS: export const run = (f: () => T): T => { return f(); };
Can you clarify why do you prefer this over an IIFE `(() => {...})()`?
Re: Rust's Block Pattern
#93I love that this is part of the syntax. 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.
Yes, I constantly use this pattern in C++/JavaScript, although I haven't tested how performant it is in the former (what does the compiler even do with such an expression?)
Re: Rust's Block Pattern
#94Earlier quoted context omitted.
That prevents other control flow mechanisms (return, break) from operating past the function boundary. In general, I avoid single-callsite functions as much as possible (including the iterator api) for this reason.
It sounds like you're fighting the language - Rust is sort of FP-light and you're encouraged to return a null/error value from the intermediate calculation instead of doing an early return from the outer scope. It's a nice and easy to follow way to structure the code IME. Yes, it's more verbose when an early return would have been just right - so be it.
Re: Rust's Block Pattern
#95I love that this is part of the syntax. 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.
(Not to be confused with do notation)
Re: Rust's Block Pattern
#96> This is why I generally avoid C’s “bottom-up” strategy for organizing code. I think the author misunderstood something....
Re: Rust's Block Pattern
#97Earlier quoted context omitted.
Many languages use this idiom. Some popular ones even. So while it's good that Rust joined them, it's hardly a differentiator.
It's a differentiator wrt C and C++, is what I said.
It is available as a language extension in Clang and GCC and widely used (e.g. by the Linux kernel).
Unfortunately it is not supported by the third major compiler out there so many projects can't or don't want to use it.
Re: Rust's Block Pattern
#98There are some situations with tricky lifetime issues that are almost impossible to write without this pattern. Trying to break code out into functions would force you to name all the types (not even possible for closures) or use generics (which can lead to difficulties specifying all required trait bounds), and `drop()` on its own is of no use since it doesn't effect the lexical lifetimes.
Conversely, I use this "block pattern" a lot, and sometimes it causes lifetime issues: 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
Re: Rust's Block Pattern
#99Block expression https://doc.rust-lang.org/reference/expressions/block-expr.h... Also in Kotlin, Scala, and nim.
Re: Rust's Block Pattern
#100Earlier quoted context omitted.
My instinct is this would get hairy much faster if you want to actually close over variables compared to using a block.
Not sure if that is relevant to your point, but: For better and for worse, closing over any outer scope variables is syntactically free in Rust lambdas. You just access them.