5 ms·
I think C++ does closures a bit better than Rust, particularly when you have lots of Arcs and Rcs. The clone dance gets old fast. However, Rust does everything
by trace_next 8y ago
I think C++ does closures a bit better than Rust, particularly when you have lots of Arcs and Rcs. The clone dance gets old fast. However, Rust does everything else so much better, especially Cargo (here's hoping Buckaroo, vcpkg, etc. gain adoption).
- eridius 8y agoC++ hides the clones from you for sure, but it means it's a lot easier to figure out in Rust where you're copying the closure (because the copies have to be explicit) and thus it's easier to reason about the performance of the Rust code.
- masklinn 8y agoThey may also be referring to the more flexible and precise capture clauses of C++ lambdas versus Rust's coarser move v non-move closures. Essentially, capture clauses are a design pattern in Rust whereas they're a language feature in C++: http://smallcultfollowing.com/babysteps/blog/2018/04/24/rust-pattern-precise-closure-capture-clauses/#a-more-general-pattern http://smallcultfollowing.com/babysteps/blog/2018/04/24/rust...
- eridius 8y agoGood point, I was thinking of cloning the closure itself, not capturing Arcs and having to clone them to avoid moves. Though in this case it would be C++'s implicit copies rather than capture clauses. In terms of capture clauses, what I really like are Swift's, as they allow you to bind identifiers to expressions in the capture clause itself (as opposed to just doing capture-by-value vs capture-by-reference). Having capture clauses in Rust that have the same capability would be great.
- pcwalton 8y agoRust used to have capture clauses, but they were removed in order to reduce the complexity of the language. It might make sense to add them back later, but given that Rust is still constantly criticized for being too complex I think it's probably still not yet time.
- masklinn 8y agoThat makes sense to me, I subscribe to the view that software "design patterns" are userland patches for things missing from the language or misuses thereof. The question is then whether the feature is missing enough (the pattern is common) that it makes sense to feed it back into built-in support or not. I don't know how common the knowledge of nikomatsakis's pattern is though, and thus if crates could be automatically searched for it.
- RReverser 8y agoIn general I agree that Rc could've been nice to copy instead of cloning explicitly, but on another hand I'm a pretty big opponent of having "lots of Arcs and Rcs" since they usually hide the ownership and data flow, and are rather hard to refactor out once added.
- gpm 8y agoI'm not very familiar with C++ closures, but I agree with rust closures having room for improvement for a different reason. Lack of fine grained control over copy/move. let settings = thing_it_wants_to_take_by_reference; let channel = thing_it_needs_to_take_ownership_of; let closure_that_takes_everything_by_reference = || { some_code(settings, channel) }; let closure_that_takes_everything_by_move = move || { some_code(settings, channel) }; let closure_that_does_what_I_want = { let ref_settings = &settings; move || { some_code(ref_settings, channel) } }; let closure_with_hypothetical_syntax = || [move channel] { some_code(settings, channel) };
- steveklabnik 8y agoThis was a fairly explicit design decision, because these cases come up so rarely. It's our opinion that it's not common enough to be worth increasing the complexity of the language. You don't even need it in this case; this will compile, for example: fn main() { let settings = String::new(); let channel = String::new(); let closure_with_hypothetical_syntax = || { some_code(&settings, channel) }; } fn some_code(settings: &String, channel: String) { } The only difference is the & on settings in the closure. This moves channel but not settings.
- gpm 8y agoWait... hmm... now I'm going to have to track down some code where I did this trick and figure out why or if I was just being stupid.
- steveklabnik 8y agoIt’s cool! In general, the default is “rust tries to capture each thing the way it needs to be” and you can use move to override that. Sometimes, you do have to do what you wrote, at least in theory. I’ve never actually had to.
- chrismorgan 8y ago
- buro9 8y agoWe had a bug once (not in this code) and we're choosing memory safe languages where possible to avoid future recurrences or similar issues.