Decided to start learning rust last month. I have very little previous programming experience and the journey has been a bit brutal so far so i wanted to share my "Learning journey".<p>"The book" although a great book, is fairly dense with no exercises. Rustlings[1] help me apply alot of my learning and i supplemented the book with Tensors programming tutorials on youtube [2]. Recently i started developing a game in Bevy[3] and although its a bit over my head at this point i've managed to get a character moving and be able to kill a monster and receive a drop. My motivations for learning rust was to be familiar with substrate [4] as i'd like to switch careers into programming. Would also love any recommendations/tips & tricks by any experience rustaceans!<p>[1]<a href="https://github.com/rust-lang/rustlings" rel="nofollow">https://github.com/rust-lang/rustlings</a>
[2]<a href="https://www.youtube.com/watch?v=EYqceb2AnkU&list=PLJbE2Yu2zumDF6BX6_RdPisRVHgzV02NW&index=1" rel="nofollow">https://www.youtube.com/watch?v=EYqceb2AnkU&list=PLJbE2Yu2zu...</a>
[3]<a href="https://bevyengine.org/learn/book/getting-started/" rel="nofollow">https://bevyengine.org/learn/book/getting-started/</a>
[4]<a href="https://www.substrate.io/" rel="nofollow">https://www.substrate.io/</a>
This little bit, which is not coming in this version but is enabled by it:<p>> f"" as a short-hand for a format string. For example, f"hello {name}" as a short-hand for the equivalent format_args!() invocation.<p>I'm excited by. I like the f-string formatting in Python quite a bit.
I love Rust, but one thing that seems like a glaring design flaw is that adding a new trait implementation can change the behavior of existing code. This is very counterintuitive, because it seems like a purely additive change. In my opinion, the convenience of auto-dereferencing "as much as possible" to make method call syntax magically work through the indirection of references is not worth the lack of stability guarantees that it causes. This isn't a normal kind of breakage where the compiler points out what code you need to fix; this is a much worse kind of breakage where you might not even realize your code now behaves differently. In my opinion, the notion of "editions" is not an acceptable solution to this.<p>For a language that prioritizes safety, there are a surprising number of gotchas in Rust (another example is the large number of partial functions in the standard library).
One thing that I repeatedly bump into in Rust is the oddity of multi-argument functions. To explain the problem, let's look at another language for a moment: in SML there is no such thing as multi-argument functions per se. There are two ways to write them anyway:<p>* the function's argument is a tuple (this is the more common way, not only in SML, but also how it's done most commonly in maths);<p>* currying.<p>I'm not a fan of currying, because it singles out the first argument over the others. However, the first approach (tuples) is very ergonomic, because now you can pass the return value of one function as an argument to a "multi-argument" function. One application of that is function composition. But another is a simple map. I've lost count of how many times in Rust I had an "o: Option<(A, B)>" and a "f: fn(A, B) -> C" and couldn't call "o.map(f)"; instead the programmer is forced to write more noisy code with lambdas. And lambdas sometimes don't play well with the borrow checker for mysterious reasons (even those that don't capture anything).<p>Also, I think it would be nice if the compiler generated named discriminants for every enum. Currently, "std::mem::discriminant" returns an opaque "std::mem::Discriminant<T>" (which doesn't have a name). In order to compare discriminants I need to create a full-blown enum value and extract the discriminant from it later. I've worked around this problem by using the "strum" crate, which has a macro to produce another (plain) enum, but having the discriminant type be named "std::mem::Discriminant<T>" (to signal the connection to the original enum) <i>and</i> have named variants at the same time would be the best of both worlds.<p>EDIT: If I knew more about possible breakage caused by my first suggestion, I could probably start working on an RFC. However, I feel I don't have enough knowledge about Rust to anticipate that.<p>For my second suggestion I think I'm going to try to propose that. I'm reading the docs on the process now.
> However, note that Rust is a project run by volunteers. We prioritize the personal well-being of everyone working on Rust over any deadlines and expectations we might have set. This could mean delaying the edition a version if necessary, or dropping a feature that turns out to be too difficult or stressful to finish in time.<p>What a refreshing take! One of the things I have admired about Rust is the effort from the start to build a healthy, welcoming, non-toxic community, and to prioritize personal well-being.
This doesn't require an edition change, but I'm really looking forward to custom, per-collection allocator support. It's in nightly right now and very nice to use.
> Starting in Rust 2021, closures will only capture the fields that they use<p>Holy shit yes. Thank you thank you thank you. This fixes my biggest annoyance so far!
> However, note that Rust is a project run by volunteers. We prioritize the personal well-being of everyone working on Rust over any deadlines and expectations we might have set. This could mean delaying the edition a version if necessary, or dropping a feature that turns out to be too difficult or stressful to finish in time.<p>I like this.
Lack of IntoIterator for arrays and disjoint capture are some of the biggest pain-points in writing Rust code for me! Very excited to see these changes on the map.
Man I feel like an idiot. I read the first paragraph and I'm like "that's just versions" and then I read the next few paragraphs and I'm like "Yeah but your dependencies are going to screw you".<p>I'm not sold on the raw identifier syntax and we'll see if the changes are actually as good as they claim, but in general this seems like a great way of doing language 'versions'.<p>Rust is definitely learning from the past and I'm really interested see what we learn from how they fuck up too
> Instead, we decided to add the [IntoIterator] trait implementation in all editions (starting in Rust 1.53.0), but add a small hack to avoid breakage until Rust 2021.<p>Eh, why not. We nerds are used to retconning in all the sci-fi universes anyway.
> It has been suggested many times to "only implement IntoIterator for arrays in Rust 2021". However, this is simply not possible. You can't have a trait implementation exist in one edition and not in another, since editions can be mixed.<p>Another example how editions aren't much different than mixing language versions on other eco-systems, just another way of achieving similar results.
The page source for this post has this comment at the end:<p><pre><code> <!--
If you really can't wait, many features are already available on
Rust [Nightly](https://doc.rust-lang.org/book/appendix-07-nightly-rust.html)
with `-Zunstable-options --edition=2021`.
--></code></pre>