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

rename with_* to set_* & add new with_* methods for vector types #597

Open
wants to merge 5 commits into
base: main
Choose a base branch
from

Conversation

ganhaque
Copy link

Objective:

The current behavior of the with_* methods for vector types is confusing since the name suggests creating and returning a modified copy of the vector without modifying the original. However, these methods currently mutate the original vector in place.

There is also no method for creating and returning a copy of the original with modified value.

Solution:

  • Renamed the current with_* method to set_* to more accurately describe their mutating nature.
  • Added a new with_* method to create a copy with modified value.

@aloucks
Copy link
Contributor

aloucks commented Jan 20, 2025

Usually I've seen and expect with_ methods to take the object by value and return itself. Where as set_ methods take a &mut self receiver. The convention in this proposed change does not make sense to me.

These are all copy types anyway. The existing with_ methods copy the item and return a modified copy. I don't see the point of adding the set_ variants.

@ganhaque
Copy link
Author

ganhaque commented Jan 21, 2025

I don't think the current with_ method copy the item and return a modified copy?

Current:

/// Creates a 3D vector from `self` with the given value of `x`.
#[inline]
#[must_use]
pub fn with_x(mut self, x: f32) -> Self {
    self.x = x;
    self
}

New:

/// Returns a new version of this 3D vector with the given `x` value.
#[inline]
#[must_use]
pub fn with_x(&self, x: f32) -> Self {
    Self { x, ..*self }
}

I think both methods are pretty useful. The new set_ (the old with_ renamed) method provide a better way to initialize a vector type without the overhead of creating a new instance. The new with_ method is for cloning without mutating the original.

// set_ method is better for initializing
let foo = Vec3::ZERO
    .set_x(1.0);

// with_ method is better for cloning
let bar = foo.with_y(1.0);
let x = foo.with_z(1.0);

&mut self for the set_ method does make more sense than mut self. I didn't catch that when renaming the old with_ method. I fixed that in the latest commit.

@aloucks
Copy link
Contributor

aloucks commented Jan 21, 2025

I don't think the current with_ method copy the item and return a modified copy?

Yes, it creates a copy. That's what mut self means as the receiver. It consumes the old one. If the type were not Copy the old one would no longer be available. A copy is NOT created when you use &mut self (a reference type).

#[test]
fn vec3_copy() {
    let a = Vec3::splat(1.0);
    let b = a.with_x(2.0);
    assert_eq!(1.0, a.x);
    assert_eq!(2.0, b.x);
}

@ganhaque
Copy link
Author

ganhaque commented Jan 21, 2025

Ah, sorry for the misunderstanding, I though you meant create a copy as in creating a new instance with the same value (with the modified field x, y, z, etc.).

A copy is NOT created when you use &mut self (a reference type).

Yeah, that is for the set_ method which modify the original in place without consuming it. The new with_ takes an immutable reference &self and returns a new instance with the modified value, while ensuring the original instance remains unchanged and available.

@aloucks
Copy link
Contributor

aloucks commented Jan 21, 2025

Your desired behavior for the way it works is how it already works. Look at the example unit test that I posted. The current with_ methods do not modify the original.

@ganhaque
Copy link
Author

ganhaque commented Jan 21, 2025

Ah, I didn't understand how it work originally, thank you for explaining it. If both methods work, I think it would be better to explicitly create a copy instead of implicitly via the Copy trait? It would also be consistent with the current swizzle with_ methods.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants