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] http://swiftdoc.org/nightly/protocol/Arithmetic/
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.