Warning: This is a slightly rambling, stream of consciousness on a certain aspect of library design in Rust. Any advice would be appreciated.
I'm writing a library that includes some implementations of mathematical equations that I'd like to be reusable for purposes other than my library's direct goals.
To that end, I'd like them to be easy to adapt to whatever the user would like or whatever third party libraries they're using. The simplest way would be to accept plain numeric types, like so:
fn do_equation1(x: i32, y: i32, z: i32)
So if a user is using another library that provides a Coord
type, they can plug it in with do_equation(coord.x, coord.y, coord.z)
.
However as x
, y
, and z
together form a type it'd make more sense to express that in the interface, perhaps using tuples like so:
fn do_equation2((x,y,z): (i32, i32, i32)) -> (i32, i32, i32)
Which, as shown above, also has the advantage of having symmetry with functions that return x
, y
and z
. It can still be easily adapted to other types with an easy from
or into
implementation.
But if I'm going to use tuples then I might as well use a full struct, right? Except that feels more heavy weight even if it's doing the same thing. A user that's using another library's Coord
struct now has to juggle two different structs with the same layout and name but that are nonetheless different types.
So what do you think the best interface is in general? I'm minded to keep it simple. After all, the equations might turn out to useful for things that aren't coordinates, even if I haven't thought of them.
Are there any trade-offs I haven't considered? Or am I way overthinking this?