
Announcing Rust 1.26.2 - philonoist
https://blog.rust-lang.org/2018/06/05/Rust-1.26.2.html
======
steveklabnik
This is our first-ever z=2 release. Even though it's only 16 days until
1.27.0, we decided to go ahead and issue it, given the unsoundness. Happy as
always to answer questions.

~~~
zxcvhjkl
Any plans for “stack full” co-routine(go style).

IMHO the current “Futures” monad style solution makes the code look a bit
confusing.

~~~
woah
I disagree. For the use case of single thread concurrency, async/await is
easier to reason about, since you don't have the added abstraction of a
separate execution thread (that isn't even actually a different thread). With
coroutines comes the added work of deciding when to "fork", and the added work
of stringing everything together with channels and mutuxes.

I myself learned to program on node.js 6 years ago, when everything required
piles of callbacks (the least ergonomic form of async/await style
concurrency). It's strange to see a bunch of experienced programmers saying
that nobody could possibly use this style, as it is too hard, while millions
of beginning programmers master it easily. In fact I remember that the people
who usually had a problem with callbacks were those who had prior experience
with synchronous languages.

Async/await reveals the beauty of this pattern of async, by getting rid of the
syntactical cruft of promises and callbacks. It's already awesome in C# and
JS, and will be landing in Rust this year.

IMO using "thread" patterns should only be done when you actually have
something to gain, with real multi core parallelism. The big advantage of
coroutines is that they scale seamlessly across cores. By putting the bad
ergonomics of threads everywhere, you make your code ready to scale onto
actual threads.

~~~
zxcvhjkl
Look at the tokio chat example: [https://github.com/tokio-rs/tokio-
core/blob/master/examples/...](https://github.com/tokio-rs/tokio-
core/blob/master/examples/chat.rs)

    
    
      let line = io::read_until(reader, b'\n', Vec::new());
      let line = line.and_then(|(reader, vec)| {
         if vec.len() == 0 {
           Err(Error::new(ErrorKind::BrokenPipe, "broken pipe"))
         } else {
           Ok((reader, vec))
         }
      });
    
      // Convert the bytes we read into a string, and then send   that
      // string to all other connected clients.
      let line = line.map(|(reader, vec)| {
        (reader, String::from_utf8(vec))
      });
      ...
    

With monads we end up with much boilerplate that has nothing to do with the
actual "business" logic.

Maybe you prefer that, but I prefer the code to describe just the business
logic.

~~~
tatterdemalion
The same code with `await` :)

    
    
        let (reader, vec) = await { io.read_until(reader, b'\n', Vec::new() }?;
        if vec.len() == 0 {
            return Err(Error::new(ErrorKind::BrokenPipe, "broken pipe"));
        }
        let string = String::from_utf8(vec)?;

