Swift で関数一つ呼ぶのに苦労した話し

  • 50
    Like
  • 3
    Comment
More than 1 year has passed since last update.

概要

Swift では関数定義は比較的簡単にできますが、呼び出し方法にはややクセがあります。
感覚でコードを書いてるとハマります。古いドキュメント等を見ててもハマります。

関数呼び出し方法

引数が 1 つ 引数が 2 つ以上
ラベル無し ①呼び出し時に引数名は不要 ②2 つめ以降は引数名を指定して呼び出し
ラベル有り ③ラベルを指定して呼び出し ④ラベルを指定して呼び出し

②ラベル無し、かつ複数の引数を持つ関数 の呼び出し方法には注意が必要。

サンプル

①ラベル無し・引数 1 つ

func myFunc1(str1:String) {
    println("str1=\(str1)")
}

// 引数名は不要
myFunc1("foo") // OK
myFunc1(str1: "foo") // Extraneous argument label 'str1:' in call

②ラベル無し・引数複数

func myFunc2(str1:String, str2:String) {
    println("str1=\(str1), str2=\(str2)")
}

// 2 つめ以降の引数には引数名が必要(1 つめの引数には不要)
myFunc2("foo", "bar") // Missing argument label 'str2:' in call
myFunc2(str1: "foo", str2: "bar") // Extraneous argument label 'str1:' in call
myFunc2("foo", str2: "bar") // OK

③ラベル有り・引数 1 つ

func myFunc3(label1 str1:String) {
    println("str1=\(str1)")
}

# ラベルが存在する場合は(引数名ではなく)ラベルをつけて呼び出す
myFunc3("foo") // Missing argument label 'label1:' in call
myFunc3(str1: "foo") // Incorrect argument label in call (have 'str1:', expected 'label1:')
myFunc3(label1: "foo") // OK

④ラベル有り・引数複数

func myFunc4(label1 str1:String, label2 str2:String) {
    println("str1=\(str1), str2=\(str2)")
}

# ラベルが存在する場合は(引数名ではなく)ラベルをつけて呼び出す
myFunc4("foo", "bar") // Missing argument label 'label1:label2:' in call
myFunc4(str1: "foo", str2: "bar") // Incorrect argument label in call (have 'str1:str2', expected 'label1:label2')
myFunc4(label1: "foo", label2: "bar") // OK
myFunc4(label1: "foo", str2: "bar") // Incorrect argument label in call (have 'label1:str2', expected 'label1:label2')

Playground で試すと挙動が違う?

Playground で試すとラベル名が指定されていない関数に関しては、
(複数引数が存在する場合でも)引数名を設定する必要がないです。

Playground で利用している Swift のバージョンが異なるのでしょか?
XCode の設定の問題でしょか?なんでだろう。

関数呼び出し方法

引数が 1 つ 引数が 2 つ以上
ラベル無し ①呼び出し時に引数名は不要 ②呼び出しの際に引数名不要(ここが違う)
ラベル有り ③ラベルを指定して呼び出し ④ラベルを指定して呼び出し

①ラベル無し・引数 1 つ

func myFunc1(str1:String) {
    println("str1=\(str1)")
}

// 引数名は不要
myFunc1("foo") // OK
myFunc1(str1: "foo") // Extraneous argument label 'str1:' in call

②ラベル無し・引数複数

func myFunc2(str1:String, str2:String) {
    println("str1=\(str1), str2=\(str2)")
}

// 引数名は不要(!)
myFunc2("foo", "bar") // OK
myFunc2(str1: "foo", str2: "bar") // Extraneous argument label 'str1:str2:' in call
myFunc2("foo", str2: "bar") // Extraneous argument label 'str2:' in call