I have written my first Rust crate: kmedoids.

Python users can use the wrapper package kmedoids.

It implements k-medoids clustering, and includes our new FasterPAM algorithm that drastically reduces the computational overhead. As long as you can afford to compute the distance matrix of your data set, clustering it with k-medoids is now feasible even for large k. (If your data is continuous and you are interested in minimizing squared errors, k-means surely remains the better choice!)

My take on Rust so far:

  • Pedantic. Which is good if you want quality code. Which is bad if you want others to contribute.
  • Run time was very fast, I liked that. The pedanticness gives the compiler additional information to optimize better, of course.
  • Tooling is okay, but can be improved. Compilers give good error messages, but the color scheme assumes a black background terminal.
  • I’d prefer to have it properly integrated in my OS, rather than having yet-another-package-manager in the form of rustup. This is the road to madness that everything now brings its own package manager, this should be part of the operating system.
  • The python module generation with PyO3 is crazy shit, but cool to have.
  • I like the exception handling and optionals so far. And with Rust you know that it will be optimize out very well. With Java you know pretty well that it wont when you’d most need it…
  • It is a pity that there seems to be a secret Rust convention to never documentation internal functions or code, only APIs. Java overdid it the other direction with the convention of documenting stupid getters and setters, but there ought to be a middle ground.
  • They overdid it with making everything as few characters as possible. Code does not get better if its shorter. I have never been a fan of omitting “return” statements (just 6 chars)! But Rust is not the worst here because at least it has strong typing. Implicit returns are error-prone.
  • A simple for i in 0..n { already causes a clippy warning; the clippy rule clearly is overshooting its own description. It fails to detect if the index i is actually needed. So the alternative would be a for (i, item) in list.iter().enumerate() {. And apparently there is some weird reason why iterators are even faster than a range for loop?!?
  • My first interactions with the Rust community were not particularly welcoming.

Will I use it more?

I don’t know. Probably if I need extreme performance, but I likely would not want to do everything my self in a pedantic language. So community is key, and I do not see Rust shine there.