Asignación personalizada de Swift a tupla

Tengo una estructura para contener un valor bruto y una tirada de dado

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
  }
}

y dos jugadores, así que mantén los valores en una tupla

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

Cuando necesito sumar o restar modificadores a las puntuaciones de los jugadores, uso una tupla de (Int, Int)

(1, -1)

y modificar las partituras con un operador personalizado

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))
}

En lugar de usar una adición y una asignación para modificar las puntuaciones de esta manera:

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

Pensé que podría usar este operador de asignación

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

Pero

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

da este error:

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

Supongo que tiene que ver con la forma en que se asignan las tuplas, pero ¿alguien sabe cuál es el problema y si se puede hacer que funcione?

Answer

(myScore, hisScore) += (1, -1)no funciona porque (myScore, hisScore)no es una cosa mutable. esto es como decir

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

myScorey hisScoreellos mismos son mutables, pero la coincidencia de patrones solo funciona en el lado izquierdo de =, no en +=.

Si en cambio pones la tupla en una sola variable:

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

Entonces puedes hacer:

scores += (1, 2)

Para que sea posible acceder a las puntuaciones con myScorey theirScore, puede agregar etiquetas de parámetros a la tupla:

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
}

También considere cambiar esto a a structsi no va a coincidir mucho con el patrón en la tupla.