kvark / mint

Math Interoperability Types
MIT License
256 stars 20 forks source link

From<Vector2> for (f32, f32) and friends #72

Open thomak-dev opened 3 years ago

thomak-dev commented 3 years ago

There are some libraries that use tuples like this. E.g. glyph_brush's Section::with_bounds takes a Into<(f32, f32)>. So I need to match or something if I want to pass a Vector2. (I actually do this many times in my code). Implementing this trait and related traits would probably make many peoples code a bit less verbose.

I wouldn't mind to contribute this.

This issue probably implies both From<VectorN<T>> for (T1, ..., TN) as well as From<(T1, ..., TN)> for VectorN<T>. The same for Point.

Ralith commented 3 years ago

Sound reasonable to me!

kvark commented 3 years ago

Could you provide more info on the usage, please? I.e. what kind of code would use mint types and call into glyph_brush?

It seems to me that the case you described is a problem with glyph_brush, since it considers (f32, f32) to be that portable representation of a vector that mint wants to be. So a proper solution would be changing the API in glyph_brush to accept Into<mint::Vector2<f32>>.

thomak-dev commented 3 years ago

Let's say I have a public interface "draw_text(position: mint::Vector2, ...)" and inside the implementation I simply want to pass the Vector2 to a library function that I have no control over that takes a (f32, f32) or the Into<> version like glyph_brush. Currently I have to either first convert into a mint-able type that has a Into tuple impl (e.g. glam::Vec2::from(position).into()) or do some other "ad hoc" conversion.

I understand that in the ideal world glyph_brush would instead use Into<mint::Vector2> and I agree that that would be better. However this would only solve the problem for glyph_brush which I only used as an example. There are probably more libraries that use tuples as parameters.

I think implementing tuple conversions are a low hanging fruit compared to updating every library to use mint. I can imagine that some libraries do not care much about linear algebra and stuff so they just use a tuple.

Ralith commented 3 years ago

IMO tuple conversions make just as much sense as array conversions, and we've already got those.

kvark commented 2 years ago

I'm not objecting hard on this. I want to present a different viewpoint.

mint main goal is to help library authors to interact with users better. So it helps the user-author API boundary. In this case @thomak-dev described, users are happy with Mint on the outside, so no issue. The issue they are describing is for library implementors. I think it's acceptable to have this issue, because there are much more users than library implementors. And it's not like Mint punishes library implementors in general - it's only mildly inconvenient when there is a dependency not integrated into Mint, and it uses tuples. This can be expected that dealing with non-Minted APIs can be less convenient.

thomak-dev commented 2 years ago

I have another perspective on this: If mint is for interoperability between Vector-like types, why is tuple not being considered such a type? Isn't it kinda arbitrary?

kvark commented 2 years ago

Originally, Mint was made for interop between math libraries. I don't know any math library that uses tuples for vectors. So the trade-off here is the following: 95% uses of mint would not benefit from (f32, f32) conversion code. But it would still be parsed by Rust and would have to be dead-code eliminated.

Now about how heavy this is. The core of mint logic (which isn't much) is pretty much converting to/from fixed-size arrays. So it seems to me that adding conversions to/from tuples is close to doubling the amount of code generated here.

One experiment that would help to clarify this trade-off is:

Tropix126 commented 1 week ago

Can I at least suggest a conversion between (T, T) <-> Point2<T> and (T, T, T) <-> Point3<T>. This feels pretty natural and I don't believe it would significantly affect anything. Points are very commonly represented in the format (x, y)/(x, y, z) making it pretty obvious what the tuple represents, and I think there is a benefit to user-facing APIs that take/return mint types being able to convert mint types in this representation.

For some context, I have a public function that takes an impl Into<mint::Point2<f64>>. Consumers of the crate can pass in a [f64; 2] to this function, but NOT a (f64, f64) (which I would argue is a more obvious representation of a point than an array of length 2). Yes, this is kind of pedantic and the user could just construct a mint::Point2 using struct initialization, but it does seem weird that these two types can't be converted on the basis that the rust compiler "might" take more time parse conversions out.