If we were to create a Rust version of this page for Haskell, what cool programming techniques would you add to it?
Rust isn’t really a language that lends itself to terse point-free functional idioms… The sort of examples I might want to share would probably require a bit more context, certainly more code. Like I think type guards and arena allocation are cool and useful tricks but I don’t think I could write a neat little example showing or motivating either
Yeah I don’t mean just terse functional idioms. Any programming technique that blew your mind the first time you came across it would qualify.
Type guards, then :) very cool, much compiler power, love it
Do you mean RAII guards
https://rust-unofficial.github.io/patterns/patterns/behavioural/RAII.html
Or match guards?
https://doc.rust-lang.org/rust-by-example/flow_control/match/guard.html
Maybe they’re referring to “where clauses”?
Indeed I am. Forgot the name, lol, not worked with rust for a few months 😅
One thing I like a lot about Rust is that it rarely does blow my mind.
But one crate that actually did blow my mind is corosensei. It’s not Rust per se that is so crazy here, but the way it’s essentially implementing a new language feature with assembly code. This is how you know Rust really is a systems programming language. I invite you to read the source code.
Oh wow I’ve been looking for something nice like that for ages. Python can do this and it’s really great for silicon verification test stimulus. I’ve also done it in C++ using C++20 coroutines, but they are so complicated and low level I ended up having to use a library to help (libcoro). Felt like a bit of a gap in Rust, but this looks like a great solution!
Not exactly the same thing but this is still pretty funny. This is code that is technically 100% legal Rust but you should definitely never write such code 😅.
A cool thing you can do, is to store values of all kinds of types in a big HashMap, basically by storing their
TypeId
and casting them toBox<dyn Any>
(see std::any).
Then you can later retrieve those values by specifying the type (and optionally another ID for storing multiple values of the same type).So, you can create an API which is used like this:
let value = MyType::new(); storage.insert(value); let retrieved = storage.get::<MyType>(); assert_eq!(retrieved, value);
There’s various ECS storage libraries which also implement such an API. Depending on what you’re doing, you might prefer to use those rather than implementing it yourself, but it’s not too difficult to implement yourself.
What if I specify the wrong type?
let retrieved = storage.get::<SomeOtherType>();
?Is it a runtime error or a compile time error?
To answer my own question: I believe it’s a runtime error: https://doc.rust-lang.org/stable/std/any/trait.Any.html#method.downcast
Well, you would determine the
TypeId
ofSomeOtherType
, then search for that as the key in your HashMap and get back aNone
, because no entry exists and then you’d hand that back to the user.
I guess, my little usage example should’ve included handling of anOption
value…So, it’s only a runtime error, if you decide to
.unwrap()
or similar.
Something i didnt know for a long time (even though its mentioned in the book pretty sure) is that enum discriminants work like functions
#[derive(Debug, PartialEq, Eq)] enum Foo { Bar(i32), } let x: Vec<_> = [1, 2, 3] .into_iter() .map(Foo::Bar) .collect(); assert_eq!( x, vec![Foo::Bar(1), Foo::Bar(2), Foo::Bar(3)] );
Not too crazy but its something that blew my mind when i first saw it
Yea it’s like when we write
Some(2)
. It’s not a function call but a variant of theOption
enum.Enum constructors are functions, this typechecks:
fn foo<T>() { let f: fn(T) -> Option<T> = Some; }
I was a bit apprehensive because rust has like a gazillion different function types but here it seems to work like just any other language with a HM type system.
Clippy will warn you if you don’t use this feature.
This works with anything that one might call “named tuples”.
So, you can also define a struct like so and it’ll work:
struct Baz(i32);
On the other hand, if you define an enum variant with the normal struct syntax, it does not work:
enum Foo { ... Qux { something: i32 } //cannot omit braces }
I’d like to see a Rust solution to Tony Morris’s tic tac toe challenge:
https://blog.tmorris.net/posts/scala-exercise-with-types-and-abstraction/index.html
His rant about it is here:
I did a Haskell GADT solution some time back and it’s supposed to be doable in Java and in C++. Probably Rust too. I wonder about Ada.
This could be done almost trivially using the typestate pattern: https://zerotomastery.io/blog/rust-typestate-patterns/.