A bit of background: I'm an experienced programmer who's worked in over 20 languages including some esoteric ones, and I finally sat down to learn Rust and bumped into what I'm sure are common issues.
Unusually, I'm struggling to find good solutions to these, which is a concern because typically picking up each new language has been easier than the last.
Issue #1: How do I access the iterator itself in a for loop? I.e.:
for x in vec.iter() {
...
// once we reach a certain point, pass the rest as a slice to some other function
if *x == 123 { foo( the_iter.as_slice() ); }
...
}
Yes, I know, I can manually write out the de-sugared loop, but here's the thing: the iterator trait is very rich, and the standard library implementations of it often extend it even further. Why hide this functionality in such a common use-case?
Maybe something like this could work, with analogy to the similar if let
pattern:
for x in let i = vec.iter() { ... }
Issue #2: Many refactorings I would expect to work... don't. I understand the reason why, such as automatic dereferencing working in some cases but not others. The concern I have is that Rust seems to be treading on dangerous ground, where IntelliJ-style tools will forever be highly restricted. For example, I came across many scenarios like the following:
This is artificially simplified to highlight the problem: x
looks like a u8
to beginners, but is a &u8
because iterators return references. For further confusion, the closure body will automatically deref this, hiding the fact that it's actually a reference. Move the code out and it just breaks. It can get really ugly when you have complex iterators with nested references, e.g.: &&[T], which I guarantee is going to cause far too much confusion to beginner programmers in similar scenarios. Also note the trivial looking refactoring that I'm used to using without issue in every other language.
Issue #3: How do I create a mutable reference to non-mutable things? The documentation is unclear on the more complex corner-cases, which the C++ documentation for comparison covered reasonably well, such as the difference between a "constant pointer to a mutable thing" versus a "mutable pointer to a constant thing".
Issue #4 What is the idiomatic Rust way of creating the equivalent of many similar classes sharing a large base class? I've been trying to convert some Java and C# libraries, and they often re-use the same huge chunk of code with minor overrides (in the literal virtual function sense) in child classes to produce a wide range of functionality while maintaining DRY principles.
It would be nice if Rust enums
could have a common part, e.g.:
enum Person {
first: String,
last: String,
email: String
Contact(),
Employee { id: String },
Contractor { company: String, contract: String }
}
Or if enums could derive from structs, or... something. All of the "roll your own" OO-equivalent solutions I've seen in rust were for trivial examples with just 1 or 2 common members. What's the solution for 20+ common members?