Swift custom assignment to tuple

Viewed 44

I have a struct to contain a raw value and a die roll

var diceRoll: Int {
  Int.random(in: 1...6)
}

struct Score {
  var raw: Int
  let roll: Int
  
  init(_  raw: Int) {
    self.raw = raw
    self.roll = diceRoll
  }
  
  init(raw: Int, roll: Int) {
    self.roll = roll
    self.raw = raw
  }
}

and two players, so keep the values in a tuple

var (myScore, hisScore) = (Score(4), Score(3))

When I need to add or subtract modifiers to the players' scores, I use a tuple of (Int, Int)

(1, -1)

and modify the Scores with a custom operator

func +(lhs: (Score, Score), rhs: (Int, Int)) -> (Score, Score) {
  (Score(raw: lhs.0.raw + rhs.0, roll: lhs.0.roll), Score(raw: lhs.1.raw + rhs.1, roll: lhs.1.roll))
}

Instead of using an addition and an assignment to modify the Scores like this:

(myScore, hisScore) = (myScore, hisScore) + (1, -1)

I thought I could use this assignment operator

func +=(lhs: inout (Score, Score), rhs: (Int, Int)) {
  lhs = lhs + rhs
}

But

(myScore, hisScore) += (1, -1)

gives this error:

Binary operator '+=' cannot be applied to operands of type '(Score, Score)' and '(Int, Int)'

I assume that it has to do with the way Tuples are assigned, but does anyone know what the problem is, and if it can be made to work?

1 Answers

(myScore, hisScore) += (1, -1) doesn't work because (myScore, hisScore) is not a mutable thing. This is like saying

(1, 2, 3) += (4, 5, 6)

myScore and hisScore themselves are mutable, but pattern matching only works on the left hand side of =, not +=.

If you instead put the tuple into a single variable:

var scores = (Score(4), Score(3))

Then you can do:

scores += (1, 2)

To make it possible to access the scores with myScore and theirScore, you can add parameter labels to the tuple:

typealias Scores = (myScore: Score, theirScore: Score)
var scores: Scores = (Score(4), Score(3))

// you would also need to change the parameter type:
func +=(lhs: inout Scores, rhs: (Int, Int)) {
    lhs = lhs + rhs
}

Also consider changing this to a struct if you are not going to be pattern matching on the tuple much.

Related