Skip to content

Harder design decisions

Yoan edited this page Dec 29, 2017 · 2 revisions

Clone avoidance in trait bounds

It's easy to go crazy by putting T: Clone instead of T: Copy throughout the library's API.
That's what I used to do in vek's early days.

But the question would be "Heeey what about my Vec4<BigInt> ??? Can I has Vec4::broadcast(bigint) pls ??".
My answer would be: write your own convenience functions for the purpose. All fields are public; You can do anything!

vek, for one, isn't going to clone() everything behind your back (if not for the fact that clone() makes internals a pain to write).

Minimize trait bound requirements (don't impose some common Element trait)

Yeah, it might be a pain to write that where T: Sub<T,Output=T> + Mul<T,Output=T> + Sum + Neg<Output=T> slug for the N-th time, but users will thank you when their esoteric types implement not much more than these few operations.
More generally and while I'm at it, I find Rust's orphan rules to be kind of a PITA sometimes (but not only might I change my mind, the orphan rules are also subject to improvements in the future. I can't wait!).

Some functionality is so useful, it should be available even if relevant traits are not imported

I don't want users to have to import traits for unlocking functionalities, but, that being said, having them and implementing them is convenient.

Here's a typical example of what I want, for most traits:

  1. All vectors have zero() and is_zero() methods.
  2. They also happen to impl Zero, using these.
  3. At the end of the day, users don't need to import the Zero trait to call zero() on vectors, but vectors still do implement this trait, which is useful for generics.

Which traits fall into this category is fairly arbitrary. In fact, it's completely arbitrary and a matter of personal taste. There's no rule!
For instance, vectors provide their own Lerp and Slerp implementations. But Transforms do not!

I'm not sure myself about this choice. Let's see how well it works in the wild!

assert!() vs debug_assert!()

Basically, assert!() when memory safety is on the line; debug_assert!() otherwise.

For instance, perspective projection matrices validate their input with debug_assert!(), because even though invalid input may give funny results, it is still not unsafe.