user3467312
user3467312

Reputation: 69

Swift, generic function: Why is one argument label needed, the other is not?

The Swift Playground has this function:

func repeatItem<Item>(item: Item, numberOfTimes: Int) -> [Item] {
    var result = [Item]()
    for _ in 0..<numberOfTimes {
         result.append(item)
    }
    return result
}
let strArray: [String] = repeatItem("knock", numberOfTimes:4) //!!!!

Why is there a numberOfTimes: in the function call and why does removing it give me the error "missing argument label"? More confusingly, why does adding an argument label to "knock" give me "extraneous argument label"?

EDIT:

Also this piece of code has not arguments labels in the call:

func anyCommonElements <T: SequenceType, U: SequenceType where T.Generator.Element: Equatable, T.Generator.Element == U.Generator.Element> (lhs: T, _ rhs: U) -> Bool {
    for lhsItem in lhs {
        for rhsItem in rhs {
            if lhsItem == rhsItem {
                return true
            }
        }
    }
   return false
}
anyCommonElements([1, 2, 3], [3])

Upvotes: 1

Views: 254

Answers (2)

chiarotto.alessandro
chiarotto.alessandro

Reputation: 1589

func repeatItem<Item>(item: Item, numberOfTimes: Int) -> [Item] is a method that takes two parameters, the first is item and the second is named numberOfTimes. In Swift, when you call a method or a function you have to write the name of the parameters followed by ":" and the its value.

In Swift the name of the first parameter can be omitted.

Upvotes: 1

dfrib
dfrib

Reputation: 73176

Question 1

This is by construction of Swift. From Swift language guide for functions - Function Parameter Names:

By default, the first parameter omits its external name, and the second and subsequent parameters use their local name as their external name. All parameters must have unique local names. Although it’s possible for multiple parameters to have the same external name, unique external names help make your code more readable.

...

If you do not want to use an external name for the second or subsequent parameters of a function, write an underscore (_) instead of an explicit external name for that parameter.

Note from above that you can supersede this demand by placing an underscore _ in front of 2nd (and onward) parameter name. In your case:

func repeatItem<Item>(item: Item, _ numberOfTimes: Int) -> [Item] { ...

Finally note that this has nothing to do with generics, but with Swift functions in general.


Question 2

Try replacing your line

let strArray: [String] = repeatItem("knock", numberOfTimes:4) //!!!!

with

let strArray = [String](count: 4, repeatedValue: "knock")

This uses the initialiser for array objects with repeated entries.

Upvotes: 1

Related Questions