Skip to content

Commit

Permalink
Review final edits
Browse files Browse the repository at this point in the history
  • Loading branch information
atifaziz committed Feb 13, 2024
1 parent 00c9695 commit d655d1b
Showing 1 changed file with 39 additions and 29 deletions.
68 changes: 39 additions & 29 deletions src/language/custom-types/members.md
Original file line number Diff line number Diff line change
Expand Up @@ -301,6 +301,38 @@ impl Point {

In C#, you can do non-destructive mutations using `with`:

```c#
var pt = new Point(123, 456);
pt = pt with { X = 789 };
Console.WriteLine(pt.ToString()); // prints: Point { X = 789, Y = 456 }
readonly record struct Point(int X, int Y);
```

There is no `with` in Rust, but to emulate something similar in Rust, it has
to be baked into the type's design:

```rust
struct Point { x: i32, y: i32 }

impl Point {
pub fn new(x: i32, y: i32) -> Self {
Self { x, y }
}

pub fn x(&self) -> i32 { self.x }
pub fn y(&self) -> i32 { self.y }

// following methods consume self and return a new instance

pub fn set_x(self, val: i32) -> Self { Self::new(val, self.y) }
pub fn set_y(self, val: i32) -> Self { Self::new(self.x, val) }
}
```

In C#, `with` can also be used with a regular (as opposed to record) `struct`
that publicly exposes its read-write fields:

```c#
struct Point
{
Expand All @@ -316,7 +348,7 @@ pt = pt with { X = 789 };
Console.WriteLine(pt.ToString()); // prints: (789, 456)
```

Rust has a _[struct update syntax]_ that may seem similar to `with`:
Rust has a _[struct update syntax]_ that may seem similar:

```rust
mod points {
Expand All @@ -333,32 +365,10 @@ fn main() {
}
```

While `with` in C# does a non-destructive mutation (copy then update),
the [struct update syntax] does (partial) _moves_ and works fields only.
As seen in the example above, the syntax therefore requires access to
the type's fields.
Hence, it is generally more common to use it within the module that
has access to private details of its types.

To emulate something similar to `with` in Rust, it has to be baked into
the type's design:

```rust
struct Point { x: i32, y: i32 }

impl Point {
pub fn new(x: i32, y: i32) -> Self {
Self { x, y }
}

pub fn x(&self) -> i32 { self.x }
pub fn y(&self) -> i32 { self.y }

// following methods consume self and return a new instance

pub fn set_x(self, val: i32) -> Self { Self::new(val, self.y) }
pub fn set_y(self, val: i32) -> Self { Self::new(self.x, val) }
}
```
However, while `with` in C# does a non-destructive mutation (copy then
update), the [struct update syntax] does (partial) _moves_ and works with
fields only. Since the syntax requires access to the type's fields, it is
generally more common to use it within the Rust module that has access to
private details of its types.

[struct update syntax]: https://doc.rust-lang.org/stable/book/ch05-01-defining-structs.html#creating-instances-from-other-instances-with-struct-update-syntax
[struct update syntax]: https://doc.rust-lang.org/stable/book/ch05-01-defining-structs.html#creating-instances-from-other-instances-with-struct-update-syntax

0 comments on commit d655d1b

Please sign in to comment.