Six fun things to do with Rust operator overloading

abusing overloading to make custom syntax and more...

Winnie the Pooh meme: the regular Pooh has at dot_product([1.2, 3.6, 2.2], [4.0, 5.0, 6.1]) while the suit one has [1.2, 3.6, 2.2] *dot* [4.0, 5.0, 6.1]

I am not endorsing the code in this post.

C++ Input/Output#

Instead of

stdin().read_line(&mut buffer).unwrap();
println!("Hello I am {name}!!!");

we can overload the shift operators on cin and cout to allow

cin >> &mut buffer;
cout << "Hello I am " << name << "!!!" << endl;

Variadic Functions#

Instead of

std::cmp::max(x, y);
[w, x, y, z].into_iter().max();

we can make

// max+ is like std::cmp::max but better
// it supports >2 arguments
max+(x, y);
max+(w, x, y, z);

More Concise Builders#

Here's a more serious one. Builder pattern sometimes involve a lot of repeated method calls. Take for example this usage of the warp web framework.

let hi = warp::path("hello")
    .map(|param: String, agent: String| {
        format!("Hello {}, whose agent is {}", param, agent)

What if the API look like this instead?

let hi = warp::path("hello")
	+	warp::path::param()
	+	warp::header("user-agent")
	>>	|param: String, agent: String| {
			format!("Hello {}, whose agent is {}", param, agent)

Infix Functions#

Instead of

dot_product(a, b);

we can make

x ^pow^ y;
a *dot* b;
a *cross* (b *cross* c *cross* d);

Lots of people wanted this!


std::mem provides these functions


Turbofish enthusiasts would enjoy size_of but not so much size_of_val, so let's make our own improved version of size_of_val that's more turbofishy


Join and Race#

Futures combinators can have short-circuiting behaviors

// quit if any of the 3 errors
(fut1, fut2, fut3).try_join().await;

// quit if any of the 3 succeeds
(fut4, fut5, fut6).race_ok().await;

let's communicate this through & and |

(TryJoin >> fut1 & fut2 & fut3).await;
(RaceOk >> fut4 | fut5 | fut6).await;

Useful Links#