Extender los tipos de matriz usando la cláusula where en Swift


Me gustaría usar el framework Accelerate para extender [Float] y [Double] pero cada uno de estos requiere una implementación diferente.

Probé lo obvio:

extension Array<Float> {
}

Y obtener este error:

" Extensión restringida debe declararse en el genérico no especializado escriba 'Array' con restricciones especificadas por una cláusula' where '"

¿Es posible extender los tipos genéricos en Swift 2 de esta manera?

Tengo el código funcionando como se esperaba ahora. Aca un ejemplo que muestra una suma utilizando el marco Accelerate.

extension _ArrayType where Generator.Element == Float {

    func quickSum() -> Float {
        var result: Float = 0
        if var x = self as? [Float] {
            vDSP_sve(&x, 1, &result, vDSP_Length(x.count))
        }
        return result
    }
}

extension _ArrayType where Generator.Element == Double {

    func quickSum() -> Double {
        var result: Double = 0
        if var x = self as? [Double] {
            vDSP_sveD(&x, 1, &result, vDSP_Length(x.count))
        }
        return result
    }
}
Author: GScrivs, 2015-08-04

6 answers

Si desea extender solo la matriz con un tipo específico. Debe extender el protocolo _ArrayType.

extension _ArrayType where Generator.Element == Int {

   func doSomething() {
       ... 
   }
}

Si extiende Array solo puede asegurarse de que su elemento esté conformado por algún otro protocolo. i. e:

extension Array where Element: Equatable {

   func doSomething() {
       ... 
   }
}

Actualizado: Con Swift 3.1 https://github.com/apple/swift/blob/master/CHANGELOG.md

extension Array where Element == Int {

   func doSomething() {
       ... 
   }
}
 103
Author: Huy Le,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-10-07 04:15:51

¡Swift 3 al rescate!!

extension Collection where Iterator.Element == Int {
    // `Collection` can be `Sequence`, etc
}
 28
Author: Ben Lu,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-09-28 23:06:19

¿Qué tal

extension CollectionType where Generator.Element == Double {

}

O Si quieres un poco más:

protocol ArithmeticType {
    func +(lhs: Self, rhs: Self) -> Self
    func -(lhs: Self, rhs: Self) -> Self
    func *(lhs: Self, rhs: Self) -> Self
    func /(lhs: Self, rhs: Self) -> Self
}

extension Double : ArithmeticType {}
extension Float : ArithmeticType {}

extension SequenceType where Generator.Element : protocol<FloatLiteralConvertible, ArithmeticType> {
    var sum : Generator.Element {
        return reduce(0.0, combine: +)
    }

    var product : Generator.Element {
        return reduce(1.0, combine: *)
    }
}


stride(from: 1.0, through: 10.0, by: 1.0).sum   // 55
[1.5, 2.0, 3.5, 4.0, 5.5].product               // 231

Funciona con Double y Float o de cualquier otro tipo que se ajustan a los protocolos ArithmeticType y FloatLiteralConvertible. Si necesita acceder a índices específicos de su matriz, cambie SequenceType a CollectionType ya que no puede hacer esto con una secuencia.

 15
Author: Kametrixom,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-10-27 22:39:47

Así que no leí la pregunta correctamente. FloatingPointType es un protocolo existente que es implementado por Double, Float y CGFloat, por lo que

Sí. Lo hice ayer para agregar una función a SequenceType donde los elementos tenían que ser Equatable. Esta es una modificación para restringir los elementos a Float

Necesita usar una cláusula where. Esta es mi función a continuación.

public extension SequenceType where Self.Generator.Element: FloatingPointType
{
    public func splitAt(separator: Generator.Element) -> [[Generator.Element]]
    {
        var ret: [[Generator.Element]] = []
        var thisPart: [Generator.Element] = []

        for element in self
        {
            if element == separator
            {
                ret.append(thisPart)
                thisPart = []
            }
            else
            {
                thisPart.append(element)
            }
        }
        ret.append(thisPart)
        return ret
    }
}

[Float(1), Float(2), Float(3), Float(4)].splitAt(Float(2))
// returns [[1],[3, 4]]
[Double(1), Double(2), Double(3), Double(4)].splitAt(Double(3))
// returns [[1, 2],[4]]

NB No pude hacer que esto funcione para una matriz, pero SequenceType es más general de todos modos.

 4
Author: JeremyP,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2015-08-04 10:52:11

Swift 3 en Xcode 8.2

Solo necesita extender el protocolo de secuencia y proporcionar una instrucción where.

let someString = "1, 2, 3, 4, 5, 6, 7, 8"

extension String {        
  func toArrayOfElements() -> [String] {
    return self.components(separatedBy: ", ")
  }        
}

extension Sequence where Iterator.Element == String {        
  func toInt() -> [Int] {            
    return self.map {
      Int($0)!
    }
  }        
}

let arrayOfStrings = someString.toArrayOfElements()    
print(arrayOfStrings)

let arrayOfInts = arrayOfStrings.toInt()    
print(arrayOfInts)
 4
Author: Melvin John,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-02-23 23:47:20

Si solo desea extender un Array específico, debe usar un protocolo para cada tipo:

protocol DoubleValue {
    var value: Double { get }
}
extension Double: DoubleValue {
    var value: Double { return self }
}
extension Array where Element: DoubleValue {
    // use the value property
}

// the same for Float
protocol FloatValue {
    var value: Float { get }
}

extension Float: FloatValue {
    var value: Float { return self }
}
extension Array where Element: FloatValue {
    // use the value property
}
 3
Author: Qbyte,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2015-08-04 10:42:13