transportation the programming meaning lenguaje language español swift

the - swift wikipedia



Genéricos de Swift: que requieren habilidades de suma y multiplicación de un tipo (2)

Estoy probando algunos ejemplos del libro Swift, a saber, el ejemplo de matriz que tienen que introduce opciones de subíndices. Este es el código que tengo:

struct Matrix<T> { let rows: Int, columns: Int var grid: T[] var description: String { return "/(grid)" } init(rows: Int, columns: Int, initialValue: T) { self.rows = rows self.columns = columns grid = Array(count: rows * columns, repeatedValue: initialValue) } func indexIsValidForRow(row: Int, column: Int) -> Bool { return row >= 0 && row < rows && column >= 0 && column < columns } subscript(row: Int, column: Int) -> T { get { assert(indexIsValidForRow(row, column: column), "Index out of range") return grid[(row * columns) + column] } set { assert(indexIsValidForRow(row, column: column), "Index out of range") grid[(row * columns) + column] = newValue } } }

Esto se copia principalmente del libro. Una diferencia importante es en esta línea aquí:

struct Matrix<T>

Por lo que puedo decir, esto le dice al compilador que mi clase Matrix puede contener valores de tipo T, especificados por el código que usa esta clase. Ahora, me gustaría asegurarme de que el tipo T pueda compararse, así que puedo escribir esto:

struct Matrix<T: Equatable>

Esto podría ser útil en caso de que quiera comparar 2 matrices, lo que significaría comparar sus valores. También quiero proporcionar la capacidad de sumar dos matrices, por lo que también debo agregar a esta línea un protocolo que requiera que se pueda agregar el tipo ''T'' dado por el usuario de la matriz:

struct Matrix<T: Equatable, "Summable">

Igualmente, también me gustaría decir:

struct Matrix<T: Equatable, "Summable", "Multipliable">

Pregunta 1: ¿Qué nombre de protocolo puedo usar? ¿Cómo puedo conseguir esto?

En una nota relacionada, para agregar habilidades adicionales mediante el operador ''+'', debería declarar una función como esta (esto se aplica también a la multiplicación):

@infix func + (m1: Matrix<T>, m2: Matrix<T>) -> Matrix<T> { // perform addition here and return a new matrix return result }

Sin embargo, este código no es aceptado por Xcode. Más específicamente, esto ) -> Matrix<T> { produce el error: Use of undeclared type ''T'' . Lo que quiero decir con eso <T> es que el resultado será una matriz que tiene el mismo tipo de las dos matrices de entrada, pero probablemente estoy desordenando la sintaxis por completo.

Pregunta 2: ¿Cómo puedo proporcionar información de tipo al resultado de la adición?


Aquí está para su segunda pregunta (pero realmente debería hacer dos preguntas separadas):

@infix func + <T> (m1: Matrix<T>, m2: Matrix<T>) -> Matrix<T> { ... }

Para su primera pregunta: antes de resolverla, aquí está la sintaxis para definir múltiples restricciones para el parámetro de tipo:

struct Matrix<T where T: Equatable, T: Summable, T: Multipliable> {...}

O, como escribe GoZoner en los comentarios:

struct Matrix<T: protocol<Equatable, Summable, Multipliable>> {...}

Pero no lo vamos a necesitar. Primero, defina un nuevo protocolo y enumere las operaciones que necesita. Incluso puedes hacer que se extienda Equatable :

protocol SummableMultipliable: Equatable { func +(lhs: Self, rhs: Self) -> Self func *(lhs: Self, rhs: Self) -> Self }

Luego, proporcione extensiones para los tipos que desea conformar. Aquí, para Int y Double , las extensiones están incluso vacías, ya que la implementación de las operaciones necesarias está integrada:

extension Int: SummableMultipliable {} extension Double: SummableMultipliable {}

Luego, declare su restricción de tipo en el parámetro de tipo:

struct Matrix<T: SummableMultipliable> { ... }

Finalmente, puedes escribir cosas como esta:

let intMat = Matrix<Int>(rows: 3, columns: 3, initialValue: 0) let doubleMat = Matrix<Double>(rows: 3, columns: 3, initialValue: 0) let i: Int = intMat[0,0] let d: Double = doubleMat[0,0]

Lo último que necesitará es insertar la restricción de tipo en la definición de su operador:

@infix func + <T: SummableMultipliable> (m1: Matrix<T>, m2: Matrix<T>) -> Matrix<T> { ... }


Para la pregunta 1 empezar por definir un protocolo

protocol Summable { func ignore () }

Tiene un método de tirar. Luego agrégalo como una extensión a las cosas que quieres que sean sumables.

extension Int: Summable { func ignore () {} }

[Nota: Probé el método anterior para desechar, pero obtuve un error; Sospecho que Swift necesitaba algo, cualquier cosa en el protocol .]

Ahora una prueba

35> protocol Summable { func ignore () } 36> extension Int: Summable { func ignore () {} } 37> func testing<T: Summable> (x: T) -> T { return x } 38> testing(1) $R16: (Int) = 1 39> testing(1.2) <REPL>:39:1: error: cannot convert the expression''s type ''$T1'' to type ''Summable'' testing(1.2) ^~~~~~~~~~~~

Para la pregunta 2 , [editar] Use lo siguiente

@infix func +<T: Summable> (m1: Matrix<T>, m2: Matrix<T>) -> Matrix<T> { ... }

[Nota: Probé lo anterior en el REPL, que no funcionó. Pero funciona en un archivo (probablemente define un "entorno global" que REPL no)]