5

Is there a way to extend an Array when the element is a type of tuple ?

public extension Array where Element: (timeZoneName: String, formattedName: String){

}

This declaration returns 4 errors:

  • Statement cannot begin with a closure expression
  • Braced block statements is an unused closure
  • Expected '{' in extension
  • Expected identifier for type name

I can't tell if the errors shown are accurate. Any ideas?

3
  • Why don't you create a class? Commented Dec 18, 2015 at 22:47
  • Do you mean a subclass of Array ? Commented Dec 18, 2015 at 23:10
  • just a new class with those two properties Commented Dec 19, 2015 at 0:11

4 Answers 4

4

Swift 3 version of appzYourLife's answer:

extension Sequence where Iterator.Element == Tuple2 {
    func foo() {}
}
Sign up to request clarification or add additional context in comments.

Comments

4

It's now possible in Swift 3.1.

extension Array where Element == (String, String) {
    ...
}

Comments

3

Since (AFAIK) the Tuple type does not conform to a Protocol (and does not even have a name) it's very hard to do what you need.

This is the closest I could get (maybe others can provide more elegant solutions).

Typealias

First of all lets define a couple of typealiases

typealias Tuple2 = (Any, Any)
typealias Tuple3 = (Any, Any, Any)

Yes, some readers now understand where I am going and probably don't like it...

I don't like it neither

SequenceType

Now let's extend the protocol SequenceType adding the foo method when the Element of the sequence is Tuple2...

extension SequenceType where Generator.Element == Tuple2 {
    func foo() {}
}

or Tuple3

extension SequenceType where Generator.Element == Tuple3 {
    func foo() {}
}

Array

Next lets define and populate an array of Tuple2

let list: [Tuple2] = [(1,2)]

Now the extension is applied and we can write

list.foo()

Disclaimer :D

This does work only if the array is explicitly declared as [Tuple2] (or [Tuple3]).

Something like this does not work

let list = [(1,2)]
list.foo() // compile error

Comments

1

You can't add specific typing like extension Array where Element == Int because this would transform the generic Array into a non-generic version.

You will see an error something like same-type requirement makes generic parameter 'Element' non-generic

Edit

It does actually seem legit (at least in Swift 2.2) to do:

typealias tzTuple = (timeZoneName: String, formattedName: String)

extension Array where Element: tzTuple  {

}

You will have to see if this works in runtime though.

I was checking this in a Playground and at present, Playgrounds are not yet fully functional with Swift 2.2-dev

I would suggest this instead:

typealias tzTuple = (timeZoneName: String, formattedName: String)

extension Array {

  func formattedName(index: Int) -> String? {
    if self[index] is tzTuple {
      return (self[index] as! tzTuple).formattedName
    }
    return nil
  }
}

will allow you to do

let foo = [(timezoneName: "PST", formattedName: "Pacific Standard Time"),(timezoneName: "AEST", formattedName: "Australian Eastern Time")]
print(foo.formattedName(0))

2 Comments

That would be great, I´m currently using swift 2.1. Hope that the next Xcode comes with 2.2
it's a year later and there have been many changes in Swift. Rather than downvoting my original answer, either create a new correct answer or upvote alternates.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.