Hacker News new | past | comments | ask | show | jobs | submit login

I mean this is what you have to do to access variables from an async block:

    let block = || {
        let my_a = a.clone();
        let my_b = b.clone();
        let my_c = c.clone();
        async move {
            // use my_a, my_b, my_c
            let value = ...

            Ok<success::Type, error::Type>(value)
        }
    }
And you can't use `if let ... && let ...` (two lets for one if) because it doesn't desugar correctly.

And error handling and backtraces are a beautiful mess. Your signatures look like `Result<..., Box<dyn std::error::Error>>` unless you use `anyhow::Result` but then half the stuff implements std::error::Error but not Into<anyhow::Error> and you can't add the silly trait impl because of language limitations so you have to map_err everywhere.

It's not just "oh throw a box around it and you're good". It's ideas that were introduced to the language when there was lots of steam ultimately not making it to a fully polished state (maybe Moz layoffs are partly to blame IDK). Anyway I love Rust and we use it in production and have been for years, but I think there's still quite a bit to polish.




I just want to reiterate how ridiculous the async block example is. You have to add a wrapper block that captures the variables and clones them because there is no way to specify how you want variables to be captured and what works in a normal block does not work in an async block. Then, because of some other language/compiler limitations, the return type of the block can't be inferred so you have to specify it manually even when you use the block in a context where it ought be inferred trivially. All this adds up to the existence of the block syntax being more complicated than just defining a function to do the same thing (when blocks are supposed to be a convenience so that you don't need a bunch of function with context pointers taking pointers to other functions everywhere like you do in C). Which you'd happily do but wait, you're trying to curry a function for a specific use case where you pass it to an async iterator function, so the signature is fixed and you have to use a block to curry because rust doesn't support that either. So you end up with the above just to say "run this piece of code concurrently for each element in a list.


> I mean this is what you have to do to access variables from an async block:

I am clearly missing some context because that code is needlessly complex. Are you just trying to show that you have to clone values that you hold a reference to if you want to move them? Because yes, you do. But your example also needlessly borrows them in the outer closure.


It’s not needless. I explained it a bit in my previous comment but it’s not worth diving into in this forum. To get an idea, consider scenarios along the lines of transforming a list of data in parallel using an async collection/iterator where all the futures are spawned and joined within the local scope of a single function. Hit me up in the Rust Discord if you want to chat about it and go into more details. Otherwise all I can really say is that I have encountered a few scenarios where this is necessary but shouldn’t be with improvements to the compiler.




Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: