TIL about Rust ‘s Option::transpose. Pretty cool stuff:
// this will give you Result<Option<T>, E>optional.map(|v| something_that_can_fail(v)).transpose()The kind of bidirectional type inference in languages like Rust, ML, or Haskell can feel kind of unintuitive because they allow “time travel” to the future, unlike most programming languages, which evaluate expressions and statements in order. Though they make sense from the perspective of a “constraint solver.”
Think about a solver that can solve the following equation
The second equation constrains the solution to the first. Bidirectional type inference works similarly.
The article I Write Type Safe Generic Data Structures in C makes me think: many generic data structures don’t actually require type-specific code and only need to be generic over data size (and alignment) (unless dealing with C++ or Rust style non-trivial types involving destructors or other special functions). Typical C++ or Rust’s monomorphic implementation creates a lot of redundant code.
That said, I wouldn’t blame C++ or Rust. There are workarounds. A common technique in C++ is to move implementation details into non-templated functions to reduce code bloat. It’s also well known that STL implementations provide fast paths for trivial types. When combined, we can use them to reduce code-bloat caused by type-based monomorphization.
Still, there’s a certain beauty in C where every type is just dumb bytes, which naturally nudges people toward the efficient implementations.
I remember when I asked whether Rust’s iterator supports random access, I got responses like, “C++ is the only language dumb enough to turn an iterator into a mess.” No, this feature is actually very useful. Don’t be hostile to an idea just because it is from a language you dislike
This pretty much matches my limited experience using Rust to do graphics stuff. Constant breaking changes in “fundamental crates” like winit and wgpu were probably my biggest pain point.
IMO, one of Rust’s best features is the #[derive(Debug)] attribute. It significantly reduces my reliance on a debugger compared to other languages because it makes printing debug information convenient. My only minor complaint is that I wish it were enabled by default for all Rust types.
Some thoughts on RAII triggered by the recent Zig vs Rust discourse: I think it is unfair to say that the proponents of RAII don’t know its shortcomings. We could totally know the same tradeoff but just get a different conclusion.
That being said, I think linear type is a way forward. It seems to address some of RAII’s shortcomings while also preserving its strengths (see Vale and Austral). This kind of thing is one reason that I think people should keep experimenting with new languages
It seems that one of the recurring pain points of the author of “Leaving Rust Gamedev” is passing data around. It makes me wonder whether an implicit parameter system can alleviate this problem.
It annoys me that in this kind of case C++ needs a std::move shenanigan to prevent a copy. Compare this to Rust, which automatically does the correct thing without compiler optimization turned on.
https://lesley.godbolt.org/z/rnYnejsnE https://lesley.godbolt.org/z/4r8ePvW1T
About “Rust developers fear language is getting too complex,” it is a valid concern but IMO what makes a language complex is not the number of features itself. It is harmless to have features one don’t care and don’t use.
The complexity comes from language mechanics not related to a problem domain but you must understand to use a language. For example, you pretty much can’t use Rust without understanding lifetime.
Random brain rot today: “Why is Rust std::mem::transmute unsafe? It seems harmless.”
Yet, the realization struck: one can have a bit pattern that does not represent a valid value for the target type.
However, for many cases, such as transmuting an f32 to i32, are totally safe, so I wish that Rust had “conditional unsafe” for generic code.
Then I remembered how “conditional noexcept” makes duplicated expressions in interfaces in C++.
Current status: fighting to borrow checker with the abysmal amount of .clone(). Definitely need to do some major refactoring once this code works
Really awesome resource that makes me want to read the whole Rust book again.
I find C++ coroutine and async Rust quite similar to the infamous monad in that “once you understand it, you lose the ability to explain it well to others.” Perhaps some things are inherently complex.
It is interesting that both C++ coroutines and async Rust are stackless coroutines, but unlike Rust, C++ coroutine states must be dynamically allocated.
In addition, C++ coroutines is a more general-purpose feature that can model things such as generators, which I definitely wish it could reside on stack.
I am not knowledgable enough about what kind of tradeoff lead to those design decisions though.
winit, Rust ecosystem’s preferred window handling library, just did a complete overhaul of its input handling module in 0.29 which will break probably every piece of code that uses it.
This reflects a (minor) concern I have with the Rust ecosystem—frequent breaking changes result in a multitude of outdated tutorials and resources. Also, there will be tons of codebases using old library versions that fail to catch up.
Great article despite the clickbaity title Memory Safety is a Red Herring
Rust question: Why doesn’t Rust have a RandomAccessIterator? It seems to be there at some point but got removed: Trait std::iter::RandomAccessIterator
And what is the alternative? Implementing Index for the iterator?
Current status: dissatisfied with nom so decided to write my own Rust parser combinator library 
What is a good GUI option for a wgpu project? I tried egui but I can’t figure out how to integrate it (no documentation and only an outdated example)