# Why does Numeric require mutating methods?

I’m testing my current knowledge of Swift by writing an immutable `Rationals` struct:

``````struct Rational: Comparable {
let num, den, g: Int
...
``````

and I’d like for it to be `Numeric`-like (that is, `struct Rational: Numeric`, but I guess it’s called `Arithmetic` now? [1]). However, according to the documentation, `Numeric` requires mutating arithmetic operators (`+=`, `*=`, etc.).

Since my type is “fundamental” (that is, it’s more like an integer or a float than a traditional state-containing data structure), I feel it’s better to make it immutable. (The analogy for me is that just as you can’t say `5 += 1`, you shouldn’t be able to say `Rational(5,1)+=Rational(1,1)`).

Is there any way for my `Rational` struct to be `Numeric`-like, or should I abandon this plan? (How do the integers do it?)

1 Like

I would say that it’s generally not recommended to make your `struct`s immutable like this (i.e. all the stored properties are immutable), because it’s more natural for immutability to be enforced on variables holding `Rational`s. Note that making your stored properties `let`s doesn’t stop you from mutating the `struct`, e.g.

``````struct S {
let i: Int
mutating func double() {
self = S(i: i * 2)
}
}

var s = S(i: 1)
s.double()

let s2 = S(i: 1)
s2.double() // error: cannot use mutating member on immutable value: 's2' is a 'let' constant
``````

So there’s generally no point making a `struct` where all the stored properties are `let`s, and you might as well just mutate them directly instead of replacing the whole thing by assigning to `self`.

As for your analogy, the integer types in Swift are not immutable, e.g.

``````var i = 1
i += 1 // mutating is fine
Int(1) += 2 // error: left side of mutating operator isn't mutable: function call returns immutable value
``````

and your own type will work the same way, because initialisers aren’t l-values (i.e. they can’t be directly mutated but they can be assigned to a variable and then mutated). So `Rational(5,1)+=Rational(1,1))` won’t work, but `var r = Rational(5, 1); r += Rational(1, 1)` would, as expected.

6 Likes

The mutability doesn’t apply to the value itself, but to the variable it’s bound to. All the mutable requirements do is allow you to write things like:

``````var x = 5
x += 1
``````

Also, swiftdoc.org hasn’t been updated in a long time. `Arithmetic` is the old protocol from before Swift 4. `Numeric` is the current top level protocol for numbers.

1 Like

Is there a similar reference that is up to date? I especially like the type hierarchy diagrams.

3 Likes

integer and floating point types are mutable types. Integer literals are “immutable”, but they are not “integers,” similar to

If integers were immutable, then var i : Int = 5; i += 1 wouldn’t work.

If you trying to define a Rational “literal”, then I submit it should not conform to Numeric, since you’re defining a literal, like 5, not an analog to an integer type like Int. If you are trying to define a Rational number type that is an analog to an Int, then is should be mutable and then it should conform to Numeric.

I don’t believe so. The man who was maintaining swiftdoc.org was hired by Apple to work on the official docs, which, sadly, aren’t as comprehensive, even if they are more up to date.