Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support use Trait::method and/or Type::method? #1995

Open
Rufflewind opened this issue May 8, 2017 · 4 comments
Open

Support use Trait::method and/or Type::method? #1995

Rufflewind opened this issue May 8, 2017 · 4 comments
Labels
T-lang Relevant to the language team, which will review and decide on the RFC.

Comments

@Rufflewind
Copy link

Currently Rust doesn’t support any of the following:

// Example A
use Default::default;
use f64::sin;

This means one can never write default() or sin(3.14) without qualification as individual methods can never be imported in isolation. (Of course, one can also write 3.14f64.sin(), but not everyone is a fan of reverse Polish notation; this could be a deterrent for numerical users of the language.)

One workaround is to create a prelude-like module with wrappers:

// Example B
pub fn default<T: Default>() -> T { T::default() }
pub fn sin(x: f64) -> f64 { f64::sin(x) }

This is a lot of boilerplate. Perhaps it would useful to make Example A “just work”?

For static methods, the intent is pretty clear: it would enable

static_method(arg1, arg2, …)

This would be just a shorthand for calling Trait::static_method. It won’t work if Self is ambiguous.

For non-static methods, it’s not obvious what use Trait::method would do. Which among these would it enable? (Either or both?)

method(obj, arg1, arg2, …)
obj.method(arg1, arg2, …)

@petrochenkov mentioned:

Adding use Trait::AssocItem; should be simple, it mostly needs motivation and decision.
use Type::AssocItem; is not possible with current organization of compilation stages.

This issue was motivated by @HadrienG2’s Experience porting a simple MC simulation to Rust.

(The issue was moved from rust-lang/rust#41453.)

@HadrienG2
Copy link

HadrienG2 commented May 9, 2017

Thanks for opening this issue! Since I went through this little porting exercise, I've had a bunch of language/lib ideas like this written somewhere on a TODO list, but haven't allocated the time for opening appropriate issues and PRs so far.

Regarding the reverse polish notation part, I would like to clarify that what is most irksome for a non-native Rust speaker is the fact that idiomatic Rust mathematical expressions currently often need to mix and match two styles of math notations.

On one hand, we have the "functional style", commonly used by calculators, and which is by far the most widespread in other programming languages. It reads from left to right, with binary mathematical operators behaving in the usual fashion:

x = builtin_function(a * b + user_function(c/d));

On the other hand, we have the "method style", commonly used by object-oriented ayatollahs or Java programmers who do not have a choice. It feels less natural to write to most people, and is somewhat harder to read as the eye must move back and forth from left to right quite a bit more, but it plays nicely with OO and is consistent in its own way.

// Java-style
x = a.mul(b).plus((c/d).user_function()).builtin_function()

// C#-style (hurray, operator overloading!)
x = (a * b + (c/d).user_function()).builtin_function()

What is most tragic about Rust, however, is that since it is geared towards a functional programming style but implements basic mathematical operators as methods of the numerical types, people will need to mix both numerical type methods and free functions in a typical expression. So we end up with an unpleasant mixture of both styles which ultimately ends up being even less readable than either, due to inconsistent switches between left-to-right and right-to-left order:

x = (a * b + user_function(c/d)).builtin_function()

This is something that I think should be improved in order to improve Rust's usability for numerical code. This proposal is one possible way to reach this goal, though not the only one of course.

@burdges
Copy link

burdges commented May 10, 2017

It's not just reverse polish notation, but distinguishing between left vs right actions. At least one crypto library briefly confused me because method syntax pushed them into using right actions. And they work with abelian objects. lol This would not provide left actions, but sometimes function call syntax is preferable.

@withoutboats withoutboats added the T-lang Relevant to the language team, which will review and decide on the RFC. label May 13, 2017
@crumblingstatue
Copy link

rust-lang/rust#73014 was closed in favor of being able to use-import Default::default directly.

I'd like to provide an additional use-case for motivation:
Many libraries define free functions for constructors to mathy types, like vectors.

Some examples:
https://docs.rs/glam/0.24.2/src/glam/f32/vec2.rs.html#12
https://docs.rs/egui/latest/egui/fn.pos2.html

It would be nice if instead of having to create wrapper functions, the user (or the lib author with pub use) could just do use Vec2::new as vec2;

@SOF3
Copy link

SOF3 commented Jan 2, 2024

Also note that it is possible to write <_>::default() where type inference is applicable.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
T-lang Relevant to the language team, which will review and decide on the RFC.
Projects
None yet
Development

No branches or pull requests

6 participants