iBooks にある “The Swift Programming Language” の勉強メモ。Objective-C と C を普段書いている自分から、ちょっと馴染みがないものを特にまとめておきます。目次は こちら。
今回は、Function に関して。長いので 後編 はこちら。
Function
1. 複数の返り値
以前、Tuple についてみたように、関数は C と違い、いくつかの値を返すことができます。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | func count(string: String) -> (vowels: Int, consonants: Int, others: Int) { var vowels = 0, consonants = 0, others = 0 for character in string { switch String(character).lowercaseString { case "a", "e", "i", "o", "u": ++vowels case "b", "c", "d", "f", "g", "h", "j", "k", "l", "m", "n", "p", "q", "r", "s", "t", "v", "w", "x", "y", "z": ++consonants default: ++others } } return (vowels, consonants, others) } |
最後の return 文 が tuple。
1 2 3 | let total = count("some arbitrary string!") println("\(total.vowels) vowels and \(total.consonants) consonants") // prints "6 vowels and 13 consonants |
ここでは、count 関数の中で定義されているため、total tuple に対してそれぞれの名前を定義する必要はありません。
2. External Parameter Name
関数を呼ぶ際に、もっと説明的にするために、外的に引数に対して名前を付けることができます。
1 2 3 | func join(s1: String, s2: String, joiner: String) -> String { return s1 + joiner + s2 } |
この関数は、External Parameter Name がない普通の関数です。この関数を呼ぶ際には、
1 | join("hello", "world", ", ") |
とします。これだけだと、3つの String を渡す時に、それぞれどのような役割を持った String を持つのか分かりにくいです。特に第三者がコードを読む際に、あまり親切ではありません。それらを明示的に示すのが External Parameter Name です。
1 2 3 4 | func join(string s1: String, toString s2: String, withJoiner joiner: String) -> String { return s1 + joiner + s2 } |
この External Parameter Name の例は、s1 に対して、string。s2 に対して、toString。joiner に対して、withJoiner という External Parameter Name をつけています。s1 の類の変数名を、local parameter name と呼び、関数の中で使います。また、関数の中でのみ有効です。この関数を呼ぶ際には、Objective-C みたいに下記のように書きます。
1 2 | join(string: "hello", toString: "world", withJoiner: ", ") // returns "hello, world” |
External Parameter Name を定義した場合、関数を呼ぶ際には、必ず External Parameter Name もつけなければいけません。
3. External Parameter Name の省略した書き方
もし、External Parameter Name も Local Parameter Name も同じ名前であればよい時には、関数を定義する際に少し簡単に書くことができます。
1 2 3 4 5 6 7 8 | func containsCharacter(#string: String, #characterToFind: Character) -> Bool { for character in string { if character == characterToFind { return true } } return false } |
この #parameterName という書式を使うことで、External Parameter Name と Local Parameter Name を同時に定義できます。
1 2 | let containsAVee = containsCharacter(string: "aardvark", characterToFind: "v") // containsAVee equals true, because "aardvark" contains a "v” |
4. 引数のデフォルト値
デフォルトで使われる引数の値を関数定義時に指定できます。関数呼び出し時に、その引数が省略された場合には、そのデフォルト値が自動的に使用されます。
1 2 3 4 | func join(string s1: String, toString s2: String, withJoiner joiner: String = " ") -> String { return s1 + joiner + s2 } |
まずは、普通の呼び方。
1 2 | join(string: "hello", toString: "world", withJoiner: "-") // returns "hello-world" |
デフォルト値を使用する場合。
1 2 | join(string: "hello", toString: "world") // returns "hello world” |
引数のデフォルト値を定義する際は、関数定義の引数リストの最後に書くようにします。このことにより、デフォルト値がない引数をいつも同じ順番で書け、コードが読みやすくなります。
5. External Parameter Name とデフォルト値
関数の引数にデフォルトを使用する場合に、Swift は自動的に External Parameter Name を定義してくれます。例えば、
1 2 3 | func join(s1: String, s2: String, joiner: String = " ") -> String { return s1 + joiner + s2 } |
と joiner に対して自動的に同じ名前の External Parameter Name が定義されています。joiner はデフォルト値を持っているためです。そのため、関数を呼ぶ際には、
1 2 3 4 5 | join("hello", "world", joiner: "-") // returns "hello-world // or join("hello", "world") // return "hello world" |
デフォルト値を持つ引数を関数に渡す際には、External Parameter Name を省略できません。もし、どうしても External Parameter Name を使いたくない時には、_ を関数定義時に追加することで Swift が自動的に External Parameter Name を定義するのを防ぐことができます。しかし、基本的に、デフォルト値を持つ引数に External Parameter Name はあった方がよいようです。
1 2 3 4 | func join(s1: String, s2: String, _ joiner: String = " ") -> String { return s1 + joiner + s2 } join("hello", "world", "-") // now, you can do this |