4 ms·
Excited for the feature. Disappointed we didn't get something like a magic method (e.g., lang item) (which isn't without precedence [1] [2]) so we could have h
by eximius 7y ago
Excited for the feature.
Disappointed we didn't get something like a magic method (e.g., lang item) (which isn't without precedence [1] [2]) so we could have had `Future::await(fut)` or `fut.await()`.
[1] - https://manishearth.github.io/blog/2017/01/10/rust-tidbits-box-is-special/ https://manishearth.github.io/blog/2017/01/10/rust-tidbits-b...
[2] - https://manishearth.github.io/blog/2017/01/11/rust-tidbits-what-is-a-lang-item/ https://manishearth.github.io/blog/2017/01/11/rust-tidbits-w...
- eridius 7y ago`fut.await()` looks too magical. There's no hint in that expression that it's anything other than a method call. You could argue the same about `fut.await`, except in this case `await` is a keyword and thus the expression `x.await` is known to be an await expression without knowing anything about `x`, whereas `fut.await()` requires knowing the type of `fut` to understand that the method call `.await()` resolves to the lang item. Also, since it's a lang item, you could write your own nostd library that picks a different name for the same lang item and cause even more confusion.
- eximius 7y ago> There's no hint in that expression that it's anything other than a method call. Compared with `fut.await`... > There's no hint in that expression that it's anything other than a field access. At least there is precedence for functions to have magical compiler-ness for 'doing stuff', instead of overloading field access which is one of the simplest operations you can have. > ... requires knowing the type of `fut` ... tbh, you don't need to know how await works. It goes and does stuff and returns a value. If you need to know what it does, you're looking up the types and seeing, 'oh its a future' and looking at that. Contrast with the field access one and you don't even know its something else entirely. I guess I just don't buy that it can't be a method. Like, formally, yea, it isn't a well-defined, safe Rust method. But make the impl fn await(self: Self) -> Self::Target { intrinsic::await(self) } Now its a method defined on the `Future` trait, it's discoverable, it's clearly magic, it's ergonomic... In my opinion, it beats the field access one in every conceivable metric. It's just frustrating, I guess.
- Thiez 7y agoIf it's a method you should be able to create a vector of futures and `.map(Future::await)` or even `.map(Future::await as FnMut(_) -> _)`. Clearly this would never work, since `await` is implement by transforming the containing function into a state machine, your suggestion would make this impossible.
- eximius 7y agoI mean, why couldn't it? let newvec = vec![fut1, fut2, fut3].map(Future::await).collect() would be equivalent to let f1 = fut1.await(); let f2 = fut2.await(); let f3 = fut3.await(); let newvec = vec![f1,f2,f3]; or vec![fut1,fut2,fut3].map(|fut| fut.await).collect()
- Thiez 7y agoI think you fundamentally misunderstand async await. `vec[fut1, fut2, fut3].map(|fut| fut.await).collect()` will not do what you might expect, although I haven't bothered to read the RFC whether it will be allowed at all. Await must have compiler support and cannot just be some function you call.
- eximius 7y agoI am certainly being sloppy, though I think fundamentally misunderstanding it is a bit of an exaggeration. I know you can't await in a non-async function so, at the very least, you'd need (IDR the syntax for async closures?) vec![fut1, fut2, fut3].map_async(async|fut| fut.await).collect() I believe that could be built. Though, now I'm getting myself tripped up. Because I claimed that this is similar to vec![fut1, fut2, fut3].map(Future::await).collect() But I notice that I expect `await` to be a blocking, non-async function. Which, feels strange in that the lambda in the first block needs to be async but the function itself doesn't. > Await must have compiler support and cannot just be some function you call. I'm not saying it doesn't need compiler support. I explicitly state that it does - I just want the magic to be a little more explicit. Moreover, I believe that most programmers think of functions as 'encapsulated code', something that does a thing. In this sense, it matches what await does better than syntax that looks like it's accessing a field. Admittedly, in the purest sense of encapsulation, this method 'escapes' that encapsulation, but I don't consider that terribly important.
- Rusky 7y agoIf we're gonna have await share syntax with some other language feature, method syntax is IMO better than field syntax- it semantically blocks the function until the callee is complete, it evaluates to a temporary instead of an lvalue, it can unwind the caller (via cancelation, like a panic). You could implement that syntax and still make `await` a keyword, without doing the usual method lookup and without letting no_std libraries change the term, just like `.await`- that's an orthogonal concern.
- eridius 7y agoThis just then boils down to saying "the await keyword should have required parens after it", which is a different argument than saying "it should be a lang item".
- eximius 7y agohell, I'd support that. A function/method 'does a thing' while field access 'reads a thing'. Rust doesn't have implicit getters and setters like Python might have. It doesn't LOOK like `fut.await` should/could DO anything, but it can.
- eridius 7y agoAh, but isn't the whole point of an `async` function that it syntactically erases the notion of blocking on an operation? If you ignore the fact that it blocks the async function (and yields control back to the executor), then `foo.await` isn't really "doing" anything at all, it's just handing you back the future's output. Having said that, I'd have to assume that `fut.await` does consume the future, which normal field access doesn't do. Personally, I'm ok with the tradeoff that says "this keyword looks like field access but it consumes the receiver, but as a result we don't have these extra parens all over the place on a keyword", especially because going the other way introduces other costs (e.g. it looks like a method call and yet can't be referred to as Future::await).
- Rusky 7y ago