diff --git a/src/content/blog/2025-01-27T11_47_async_iterator_map.mdx b/src/content/blog/2025-01-27T11_47_async_iterator_map.mdx index 2c6d8bf..4f81fa9 100644 --- a/src/content/blog/2025-01-27T11_47_async_iterator_map.mdx +++ b/src/content/blog/2025-01-27T11_47_async_iterator_map.mdx @@ -98,7 +98,21 @@ Actually, this kind of contract isn't inherently impossible to represent in Rust As a reminder, in ref and mut member functions `'_` always refers to the self argument's lifetime, so The lifetime bound on `async_call_mut` basically declares that once it's called, its output is valid for as long as the function is in scope, and the function may not be called again until the return value is freed because for as long as it's live, so is the mutable borrow. Perfect! -But this is unstable, so what to do? Well, for the specific case of streams we can use `async_stream::stream!` with a `for` loop in a fashion a lot like the below example. + + ```rust + pub trait StreamExt: Stream { + fn then(self, f: F) -> Then + where F: AsyncFnMut(Self::Item) -> R; + } + ``` +

This would work if `AsyncFnMut` was stable.

+
+ +That's all nice and good but this is unstable and thus a non-solution for crates. So what to do? Well, you can always use a mutex as I mentioned earlier, or the boxed future if you prefer elegance over performance. This is an entirely valid position, I often take it as well. As engineers we often get lost in optimizations and long-term strategy and forget to enjoy our craft or make our products pleasant to work with. The product is certainly important, but can you place a definitive price tag on the willingness of an engineer to touch it, multiplied by engineering hours? How does that compare to the nanosecs of delay caused by an unnecessary allocation and victual call? The Ruby crowd says, very favourably. I think with Rust's performance, we have plenty of headroom for aesthetics. + +It's also worth considering that eventually `async_closure` will be standardized and when that happens, the aesthetic choice is trivially convertible, whereas removing the unnecessary mutex may have deeper design implications. + +Anyway, philosophy aside, for the specific case of streams we can also use `async_stream::stream!` with a `for` loop in a fashion a lot like the below example. ```rust stream! {