I'd like to use the Accelerate framework to extend [Float] and [Double] but each of these requires a different implementation.
我想使用加速框架来扩展[Float]和[Double],但是每一个都需要不同的实现。
I tried the obvious:
我试着显而易见的:
extension Array<Float> {
}
and get this error:
并得到这个错误:
"Constrained extension must be declared on the unspecialised generic type 'Array' with constraints specified by a 'where' clause"
“必须在非专门化的泛型类型'Array'上声明受约束的扩展,该类型'Array'具有'where'子句指定的约束”
Is it posible to extend generic types in Swift 2 in this way?
是否可以以这种方式扩展Swift 2中的泛型类型?
I've got the code working as expected now. Here's an example showing a summation using the Accelerate framework.
我已经让代码按照预期运行。这里有一个使用加速框架的求和示例。
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
}
}
6 个解决方案
#1
95
If you want to extend only array with specific type. You should extend _ArrayType protocol.
如果您只想扩展具有特定类型的数组。您应该扩展_ArrayType协议。
extension _ArrayType where Generator.Element == Int {
func doSomething() {
...
}
}
If you extend Array
you can only make sure your element is conformed some protocol else. i.e:
如果扩展数组,只能确保元素符合其他协议。即:
extension Array where Element: Equatable {
func doSomething() {
...
}
}
Updated: With Swift 3.1 https://github.com/apple/swift/blob/master/CHANGELOG.md
更新:使用Swift 3.1 https://github.com/apple/swift/blob/master/CHANGELOG.md
extension Array where Element == Int {
func doSomething() {
...
}
}
#2
27
Swift 3 to the rescue!!
快来救我!!
extension Collection where Iterator.Element == Int {
// `Collection` can be `Sequence`, etc
}
#3
14
How about
如何
extension CollectionType where Generator.Element == Double {
}
Or If you want a little bit more:
或者如果你想要更多一点:
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
Works with Double
and Float
or any other type that you conform to the protocols ArithmeticType
and FloatLiteralConvertible
. If you need to access specific indices of your array, change SequenceType
to CollectionType
as you cannot do this with a sequence.
可以使用Double和Float或任何您符合协议的其他类型。如果您需要访问数组的特定索引,请将SequenceType更改为CollectionType,因为您不能对序列进行此操作。
#4
4
So I didn't read the question properly. FloatingPointType
is an existing protocol that is implemented by Double, Float and CGFloat, so
所以我没有正确地阅读这个问题。FloatingPointType是一个现有的协议,由Double、Float和CGFloat实现
Yes. I did it only yesterday to add a function to SequenceType where the elements had to be Equatable
. This is a modification to restrict the elements to Float
是的。就在昨天,我还为SequenceType添加了一个函数,其中的元素必须是可赋值的。这是一个限制元素为浮动的修改
You need to use a where clause. This is my function below.
你需要使用where子句。这是下面的函数。
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 I couldn't make this work for an array but SequenceType is more general anyway.
NB我不能把它作为一个数组,但是SequenceType更通用。
#5
3
If you only want to extend a specific Array
you have to use a protocol for each type:
如果您只想扩展一个特定的数组,那么您必须为每种类型使用一个协议:
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
}
#6
3
Swift 3 on Xcode 8.2
Xcode 8.2上的Swift 3
Just need to extend Sequence protocol and provide a where statement.
只需扩展序列协议并提供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)
#1
95
If you want to extend only array with specific type. You should extend _ArrayType protocol.
如果您只想扩展具有特定类型的数组。您应该扩展_ArrayType协议。
extension _ArrayType where Generator.Element == Int {
func doSomething() {
...
}
}
If you extend Array
you can only make sure your element is conformed some protocol else. i.e:
如果扩展数组,只能确保元素符合其他协议。即:
extension Array where Element: Equatable {
func doSomething() {
...
}
}
Updated: With Swift 3.1 https://github.com/apple/swift/blob/master/CHANGELOG.md
更新:使用Swift 3.1 https://github.com/apple/swift/blob/master/CHANGELOG.md
extension Array where Element == Int {
func doSomething() {
...
}
}
#2
27
Swift 3 to the rescue!!
快来救我!!
extension Collection where Iterator.Element == Int {
// `Collection` can be `Sequence`, etc
}
#3
14
How about
如何
extension CollectionType where Generator.Element == Double {
}
Or If you want a little bit more:
或者如果你想要更多一点:
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
Works with Double
and Float
or any other type that you conform to the protocols ArithmeticType
and FloatLiteralConvertible
. If you need to access specific indices of your array, change SequenceType
to CollectionType
as you cannot do this with a sequence.
可以使用Double和Float或任何您符合协议的其他类型。如果您需要访问数组的特定索引,请将SequenceType更改为CollectionType,因为您不能对序列进行此操作。
#4
4
So I didn't read the question properly. FloatingPointType
is an existing protocol that is implemented by Double, Float and CGFloat, so
所以我没有正确地阅读这个问题。FloatingPointType是一个现有的协议,由Double、Float和CGFloat实现
Yes. I did it only yesterday to add a function to SequenceType where the elements had to be Equatable
. This is a modification to restrict the elements to Float
是的。就在昨天,我还为SequenceType添加了一个函数,其中的元素必须是可赋值的。这是一个限制元素为浮动的修改
You need to use a where clause. This is my function below.
你需要使用where子句。这是下面的函数。
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 I couldn't make this work for an array but SequenceType is more general anyway.
NB我不能把它作为一个数组,但是SequenceType更通用。
#5
3
If you only want to extend a specific Array
you have to use a protocol for each type:
如果您只想扩展一个特定的数组,那么您必须为每种类型使用一个协议:
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
}
#6
3
Swift 3 on Xcode 8.2
Xcode 8.2上的Swift 3
Just need to extend Sequence protocol and provide a where statement.
只需扩展序列协议并提供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)