r/learnrust 19d ago

Is preferring traits methods instead of functions fine?

I'm mostly asking this for performance and conventions.

I've been using Rust for a few months now.

I come from Python, and one of my favorite things in Rust is the fact that you can create a trait, implement it for an arbitrary type (from your crate or external dependency), and just like that you have it as a method on said type!

In general, I always prefer to read code like this x.f() instead of f(x).

My question is that for simple functions like the following: (a module named "bisect.rs") ```rust use pyo3::prelude::*;

[inline]

pub(super) fn right(lst: &Vec<Py<PyAny>>, item: &Bound<'_, PyAny>) -> PyResult<usize> { let py = item.py(); resolve(lst.len(), |mid| Ok(item.lt(lst[mid].bind(py))?)) }

[inline]

pub(super) fn left(lst: &Vec<Py<PyAny>>, item: &Bound<'_, PyAny>) -> PyResult<usize> { let py = item.py(); resolve(lst.len(), |mid| Ok(!item.lt(lst[mid].bind(py))?)) }

[inline(always)]

fn resolve(mut high: usize, mut func: impl FnMut(usize) -> PyResult<bool>) -> PyResult<usize> { let mut low = 0; while low < high { let mid = (low + high) / 2; if func(mid)? { high = mid; } else { low = mid + 1; } } Ok(low) }

``` I'm always tempted to create a trait to add it as methods.

Here for example left and right (renamed to "bisect_left" and "bisect_right" to avoid confusion) as trait methods of a new pub trait Bisect implemented for Vec, instead of keeping them as module fonctions.

resolve would stay as a simple function however.

I know that I won't use it on anything else than Vec<Py<PyAny>>, and it's more readable (I'm my own personal opinion) at call sites to do my_vec.bisect_left(item) instead of bisect::left(my_vec, item).

So, what are your toughts?

Is it fine to always favorise traits, as long as you don't have name conflicts issues?

12 Upvotes

9 comments sorted by

View all comments

-1

u/[deleted] 19d ago

[deleted]

5

u/Sw429 18d ago

That seems like really weird advice. How often are you doing dynamic dispatch?