When I first got into Rust, I didn't know what "safety" means at all. But when I try it out, I am surprised by one thing, when it compiles, it mostly works which I kinda knows what "safety" means after that. At that time, it was also interecting to see the word "zero-cost abstraction" which sounds cool.
Sometime later, when I got back into Rust, there is one project that I started working on and found interesting, which is one of those oxiding projects. https://github.com/rust-dc/fish-manpage-completions Python to Rust, I am familier with Python but Rust seemed to similar while porting it.
Lately, not sure why but I spend more time in Rust projects. I found https://github.com/maciejhirsz/beef (compact Cow) interesting so I try making my own https://github.com/pickfire/ve (compact Vec) but it wasn't exactly faster, I did it by hand-porting bit-by-bit from alloc vec library but it was not exactly faster, then I somehow found parts to improve.
What have I been doing in Rust?
- Reviewing random (easy) pull requests coming in (not sure why but I nitpick documentation quite often)
- Fixing docs and cleanup for alloc vec, I have some ideas when hand-porting it to ve
- Looking into an eager join for Iterator like collect but not there yet
- Doing some fix for rust suggestions, now
async pub
, next probably mut deref suggestion
Let us start discussing the things for Call for Posts. This post mainly talks about orthogonality and discoverability.
While using Rust for some time, I noticed that there quite some difference between str
and slice
, for example str
can take in impl Pattern
for some functions (E.g. contains
) but the same counterparts available in slice cannot do the same, but instead takes in &T
.
I get this issue while trying to change str
to slice
in https://github.com/pickfire/fs-ledger but I figured out it does not work and in the end I just stick with str
since it already work given that I need to put in more effort for less effect.
Right now as I use fish
shell, I mostly use alt-h
to view manpages but as rustup
comes with its custom man page selection based on different toolings, one needs to do rustup man
just specifically for rust man pages which in turns made me more reluctant to view rust man pages.
Without viewing rust man pages (since I thought they are the same as -h
), I missed how to do filtering for tests since I just quickly skimmed through the test
section, at the end I figured out that all these were in the man pages, if I read man pages at first, I would have already learned --lib
, --test <test>
easily.
The next thing I would say is Rust have the same issues as other languages in terms of documentation and searching for the correct types, having composition probably make the issue worse since there are too many information. Say I have a type but I want to get another type, if it requires multiple steps then it may not be straightforward to know.
Of course right now one can do * -> String
in Rust documentation, but what if there are multiple layers? Say you want to know slice -> * -> String
for as many steps as it takes. Graph database looks like a good way to discover these types but I never seen anything for these even for other languages.
I like a lot about https://lib.rs, fast, dark-mode, feature discovery and stuff except the naming since I like the word crates more. I wonder why https://crates.io still stays the same in terms of performance (most likely because it have higher load) and features?
I am not sure much about this since I am not in any team. Most of the time I just don't know who to ask since I cannot see who is in which team as only team members can see which team others are in. Even if someone reviewed my PR, I don't know if they are from that team, even my CC @rust-lang/doc or @rust-lang/rustdoc or @rust-lang/docs would not be bold and have a link, people outside the team probably cannot ping the team, or even if we did, we may not know if someone responded is from the team.
Serde is impressive, instead of defining serialization M * N
times, one could just do M + N
times. Still, as a serde user, switching between one crate and a different one with a different maintainer may not be as easy. Say, some serde crates expose Serializer
and Deserializer
types, some does not, some provides to_writer
but some does not.
In my case, I was writing a converter between serialization types https://github.com/pickfire/babelfish, I noticed that different serde libraries for different formats does things differently (especially when it was by a different author). On the other hand, I really like how rust crypto ecosystem solves this, they are able to get a lot of crates https://github.com/RustCrypto/hashes standardized to have the same functions and style but feel sad to see that some crates name was already taken and they have no choice but to use another name.
I did mentioned that I like when it compiles, it mostly works? Sadly that does seemed to be less true in the ecosystem most likely after the ability to do reflection or Any
type. Of course, the tradeoff was better ergonomics (extractors pattern) and slower speed and lesser safety (likely HashMap<Any, ??>
) which I think is fair.
Most of the web frameworks and game frameworks (this case is a bit better) I saw nowdays do panic in runtime even though it have that information at compile time but if it was done probably the ergonomics may not be as good as now. Examples,
If route data is not set for a handler, using Data extractor would cause Internal Server Error response. actix-web
If you request a State for a T that is not managed, Rocket won't call the offending route. Instead, Rocket will log an error message and return a 500 error to the client. rocket
Surprisingly, tide seemed to be safe right now but not sure if the same will happen once AppState
in https://rustasync.github.io/team/2018/10/16/tide-routing.html is implemented.
Same for game frameworks which have similar query system, like using a wrong type for Read<T>
, or Write<T>
in amethyst results a panic during runtime when the game starts, better unlike web frameworks which returns 500 only when the endpoints are called.
Code sample:
// cargo add actix-web actix-rt
use actix_web::{web, App, HttpServer, Responder};
async fn greet(_data: web::Data<String>) -> impl Responder {
"Hello world"
}
#[actix_rt::main]
async fn main() -> std::io::Result<()> {
HttpServer::new(|| App::new().route("/", web::get().to(greet)))
.bind("127.0.0.1:8000")?
.run()
.await
}
So far so good, a lot of interesting stuff have been coming up recently as discussed in https://blog.rust-lang.org/2020/09/03/Planning-2021-Roadmap.html, except it was missing cranelift which I am looking forward to. :D
Regarding documentation searching by function signature, the most unique and compelling example I know is Haskell's Hoogle .