Menu

Category

Archive

logo


The Swift Programming Language ~ Functions

2014-06-09 17:00:00 +0900
  • このエントリーをはてなブックマークに追加

iBooks にある "The Swift Programming Language" の勉強メモ。Objective-C と C を普段書いている自分から、ちょっと馴染みがないものを特にまとめておきます。目次は こちら

今回は、Function に関して。長いので 後編 はこちら。

Function

1. 複数の返り値

以前、Tuple についてみたように、関数は C と違い、いくつかの値を返すことができます。

 1 func count(string: String) -> (vowels: Int, consonants: Int, others: Int) {
 2     var vowels = 0, consonants = 0, others = 0
 3     for character in string {
 4         switch String(character).lowercaseString {
 5         case "a", "e", "i", "o", "u":
 6             ++vowels
 7         case "b", "c", "d", "f", "g", "h", "j", "k", "l", "m",
 8         "n", "p", "q", "r", "s", "t", "v", "w", "x", "y", "z":
 9             ++consonants
10         default:
11             ++others
12         }
13     }
14     return (vowels, consonants, others)
15 }

最後の return 文 が tuple。

1 let total = count("some arbitrary string!")
2 println("\(total.vowels) vowels and \(total.consonants) consonants")
3 // prints "6 vowels and 13 consonants

ここでは、count 関数の中で定義されているため、total tuple に対してそれぞれの名前を定義する必要はありません。

2. External Parameter Name

関数を呼ぶ際に、もっと説明的にするために、外的に引数に対して名前を付けることができます。

1 func join(s1: String, s2: String, joiner: String) -> String {
2     return s1 + joiner + s2
3 }

この関数は、External Parameter Name がない普通の関数です。この関数を呼ぶ際には、

1 join("hello", "world", ", ")

とします。これだけだと、3つの String を渡す時に、それぞれどのような役割を持った String を持つのか分かりにくいです。特に第三者がコードを読む際に、あまり親切ではありません。それらを明示的に示すのが External Parameter Name です。

1 func join(string s1: String, toString s2: String, withJoiner joiner: String)
2     -> String {
3         return s1 + joiner + s2
4 }

この External Parameter Name の例は、s1 に対して、string。s2 に対して、toString。joiner に対して、withJoiner という External Parameter Name をつけています。s1 の類の変数名を、local parameter name と呼び、関数の中で使います。また、関数の中でのみ有効です。この関数を呼ぶ際には、Objective-C みたいに下記のように書きます。

1 join(string: "hello", toString: "world", withJoiner: ", ")
2 // returns "hello, world”

External Parameter Name を定義した場合、関数を呼ぶ際には、必ず External Parameter Name もつけなければいけません。

3. External Parameter Name の省略した書き方

もし、External Parameter Name も Local Parameter Name も同じ名前であればよい時には、関数を定義する際に少し簡単に書くことができます。

1 func containsCharacter(#string: String, #characterToFind: Character) -> Bool {
2     for character in string {
3         if character == characterToFind {
4             return true
5         }
6     }
7     return false
8 }

この #parameterName という書式を使うことで、External Parameter Name と Local Parameter Name を同時に定義できます。

1 let containsAVee = containsCharacter(string: "aardvark", characterToFind: "v")
2 // containsAVee equals true, because "aardvark" contains a "v”

4. 引数のデフォルト値

デフォルトで使われる引数の値を関数定義時に指定できます。関数呼び出し時に、その引数が省略された場合には、そのデフォルト値が自動的に使用されます。

1 func join(string s1: String, toString s2: String,
2     withJoiner joiner: String = " ") -> String {
3         return s1 + joiner + s2
4 }

まずは、普通の呼び方。

1 join(string: "hello", toString: "world", withJoiner: "-")
2 // returns "hello-world"

デフォルト値を使用する場合。

1 join(string: "hello", toString: "world")
2 // returns "hello world”

引数のデフォルト値を定義する際は、関数定義の引数リストの最後に書くようにします。このことにより、デフォルト値がない引数をいつも同じ順番で書け、コードが読みやすくなります。

5. External Parameter Name とデフォルト値

関数の引数にデフォルトを使用する場合に、Swift は自動的に External Parameter Name を定義してくれます。例えば、

1 func join(s1: String, s2: String, joiner: String = " ") -> String {
2     return s1 + joiner + s2
3 }

と joiner に対して自動的に同じ名前の External Parameter Name が定義されています。joiner はデフォルト値を持っているためです。そのため、関数を呼ぶ際には、

1 join("hello", "world", joiner: "-")
2 // returns "hello-world
3 // or 
4 join("hello", "world")
5 // return "hello world"

デフォルト値を持つ引数を関数に渡す際には、External Parameter Name を省略できません。もし、どうしても External Parameter Name を使いたくない時には、_ を関数定義時に追加することで Swift が自動的に External Parameter Name を定義するのを防ぐことができます。しかし、基本的に、デフォルト値を持つ引数に External Parameter Name はあった方がよいようです。

1 func join(s1: String, s2: String, _ joiner: String = " ") -> String {
2     return s1 + joiner + s2
3 }        
4 join("hello", "world", "-") // now, you can do this