News for hackers. Stuff that matters.
Re:C++ Coroutines Do Not Spark Joy by kubb on Monday November 01, 2021 @06:40AM (#29065015)
I thought Rust was that better C++. It doesn't help existing large projects because nobody will ever rewrite them. However, if you're starting a C++ project in 2021 and have the option of using Rust, you might want to think twice.
Re:C++ Coroutines Do Not Spark Joy by tialaramex on Monday November 01, 2021 @07:55AM (#29065540)
There certainly are C++ programmers who express this sentiment. e.g. https://www.thecodedmessage.com/posts/hello-rust/

On the other hand, if the thing you don't like about C++ is that it keeps changing you may be unsatisfied in Rust too because Rust has in some ways an even faster pace of changes. Rust as it was written in 2015 still compiles on a modern Rust compiler (with edition set to "2015" and modulo any security issues) but it is no longer idiomatic Rust.

Re:C++ Coroutines Do Not Spark Joy by kubb on Monday November 01, 2021 @09:00AM (#29066149)
I think the OP is not complaining about change. Arguably, change is inevitable. He seems to dislike trying to keep backwards compatibility at the cost of sanity and usability, and the fact that C++ is an ever-growing pile of features that doesn't make sense anymore.

This is precisely what the Rust edition are there to solve: your legacy code will work but the language will change with each edition to reflect the state of the art, and if needed, it will break backwards compatibility.

Re:C++ Coroutines Do Not Spark Joy by CryZe on Monday November 01, 2021 @11:10AM (#29067654)
While I agree that Rust changed a lot, it was mostly fixing edge cases (like borrow checker limitations or associated types not being allowed to have generics) or obvious missing features in the language (const fn, const generics, async await) that have been known for a long time. Most of these have been implemented since then (at least in MVP form) to the point where there's barely any new ideas anymore and most old ones got implemented. So Rust really feels like it's nearing a "point of completion". You can see this with the Rust 2021 edition as well that contained very few changes.
Re:C++ Coroutines Do Not Spark Joy by nicoburns on Monday November 01, 2021 @11:01AM (#29067487)
> Rust as it was written in 2015 still compiles on a modern Rust compiler... but it is no longer idiomatic Rust.

The changes since the 2015 edition have all been relatively minor in terms of idiomatic code I think. I mean sure, you can use the '?' operator instead doing a manual match and return, but most of the changes have just been making the compiler more permissive in terms of what it accepts.

The only new concept to be learnt would be async-await, and that should be familiar to most from other languages and only applies if you're doing IO.

Re:C++ Coroutines Do Not Spark Joy by tialaramex on Monday November 01, 2021 @11:37AM (#29068153)
Today an idiomatic function that twiddles some foozles has a signature like this in Rust:

fn twiddle(foozles: impl IntoIterator<Item=Foozle>)

But in 2015 you couldn't have written that. It works in the 2015 edition today, sure enough, but it would not have worked in any 2015 Rust compiler, and so it was not idiomatic Rust in 2015.

Instead in 2015 you'd have either chosen to specify what sort of container the Foozles live in, or, if you believe freedom to choose different containers is important to your users, you have to ask the caller to Box up an Iterator over their Foozles so you don't need to care what container they used.

so e.g.

fn twiddle(foozles: Vec<Foozle>) // Hope your foozles are in a Vector or else you'll need to write an adaptor function

or

fn twiddle(foozles: Box<Iterator<Item=Foozle>>) // Now we're incurring a heap allocation

Re:C++ Coroutines Do Not Spark Joy by nicoburns on Monday November 01, 2021 @12:14PM (#29068769)
In 2015 Rust you could write:

    fn twiddle<T: Foozle, IterT: IntoIterator<Item=T>>(foozles: IterT)
which I believe would still be considered idiomatic today. (this assumes that Foozle is a trait. If Foozle is a struct then you can simplify this). You can also now use the impl syntax you posted but it's just sugar and it's less flexible than the older method.
Re:C++ Coroutines Do Not Spark Joy by wizzwizz4 on Monday November 01, 2021 @03:12PM (#29071517)
That's how I used to write it in 2018, before I discovered the `impl` keyword. It's the obvious way of doing it. (Though I'd've used `Iterator` rather than `IntoIterator` because I came from Python. (Yes, I know `IntoIterator` is the version best matching Python's behaviour.))
Re:C++ Coroutines Do Not Spark Joy by tux3 on Monday November 01, 2021 @03:24PM (#29071689)
Note that impl is not exactly equivalent. If the type passed in is ambiguous, with an explicit template the caller can disambiguate, but with impl there's no template argument.

So sometimes you still want to use the "old" syntax in your public APIs, even when you could be using an impl trait

Re:C++ Coroutines Do Not Spark Joy by chc on Monday November 01, 2021 @12:13PM (#29068757)
For what it's worth, I suspect most Rust programmers would consider twiddle(foozles: &[Foozle]) to be the most idiomatic option for general use both in 2015 and today.
Re:C++ Coroutines Do Not Spark Joy by tialaramex on Monday November 01, 2021 @02:56PM (#29071255)
Mmm, but not everything we might iterate is actually eligible to be a slice.
Re:C++ Coroutines Do Not Spark Joy by veber-alex on Monday November 01, 2021 @01:58PM (#29070386)
The only thing new in Rust 2018 is the impl Trait in argument position.

Generics and trait bounds are in the language from the start.

So you can write this function like this:

  fn twiddle<T: IntoIterator<Item = Foozle>>(foozles: T)
Which is 100% idiomatic today and is even preferred by some people over using impl Trait
Re:C++ Coroutines Do Not Spark Joy by slaymaker1907 on Monday November 01, 2021 @04:51PM (#29072942)
impl Trait as the return type actually added quite a bit more than in argument position. In particular, it allows you to return a lambda without boxing since you cannot get the exact return type of a lambda (at least not yet). impl return types are sort of a special case of existential typing.
Re:C++ Coroutines Do Not Spark Joy by gnosek on Monday November 01, 2021 @01:52PM (#29070293)
or

    fn twiddle<I>(foozles: I)
    where
      I: Iterator<Item=Foozle>
(or probably IntoIterator<Item=Foozle>). `impl T` is (modulo some details I don't remember right now) just syntactic sugar for this.
Re:C++ Coroutines Do Not Spark Joy by oconnor663 on Monday November 01, 2021 @10:16AM (#29066838)
> modulo any security issues

I'm not sure there are any security issues associated with using an older edition. I think when soundness holes and other things like that are fixed, they're usually fixed across all editions. Sometimes that's technically a backwards-incompatible change/fix, but Rust's back compat policy considers that acceptable if the breakage isn't widespread.

Re:C++ Coroutines Do Not Spark Joy by pron on Monday November 01, 2021 @02:21PM (#29070734)
Rust is a better C++. The problem is that it's a better C++, i.e. it seems to be following the same path (only faster). If in ten to fifteen years Rust will be in the same position (only with a smaller market-share) it isn't attractive enough to pay the high migration cost.
Re:C++ Coroutines Do Not Spark Joy by pas on Monday November 01, 2021 @02:43PM (#29071047)
What's missing from Rust? Or what is in it that will become a problem later?
Re:C++ Coroutines Do Not Spark Joy by slaymaker1907 on Monday November 01, 2021 @05:32PM (#29073414)
Two limitations with the type system currently are a lack of existential types as well as a lack of GADTs (general algebraic data types). Existential types would make it easier to work with unboxed lambdas when implementing a trait (since then you would be able to use type of the lambda for things like associated data types).

GADTs are useful for extremely generic code and are required if you want to write a general Monad trait. There is currently no way to write a trait which says return Self, but with a different generic argument. And not just Self, any associated type on a trait is a single type so you can't have a requirement for an associated type to be generic.

Finally, the procedural macro system is kind of a mess at the moment. Last time I checked, you really couldn't write a hygienic procedural macro (though I think this can be added later on without. A bigger limitation is that you don't really have any way to access type information in a procedural macro. Obviously type information is only available after parsing unless you make the macro system in Rust way more complicated, but it would be nice to have static type info for other modules. Having this information would allow you to do stuff like generating serialization code for some library that you don't control.

Re:C++ Coroutines Do Not Spark Joy by pron on Monday November 01, 2021 @04:40PM (#29072769)
It's probably the same as that which was missing from C++ in, say, 1990 -- the needs (and fashions) of tomorrow. But it's not specifically Rust. All languages are built for the needs of their time, and then have to adapt and change as requirements and fashions change. The question is, how do they adapt? That's defined by the language's ethos. C, C++, Java, Python, and C# have all survived and adapted for some time, but they've had somewhat different adaptation approaches. Over time, their domain also shifted (in fact, contracted compared to its peak; Python is exceptional, perhaps, in that it's peak domain wasn't its initial domain).
Re:C++ Coroutines Do Not Spark Joy by pharmakom on Monday November 01, 2021 @10:54AM (#29067360)
Rust is C++ for OCaml developers.