Swiftで作るToDoアプリ開発チュートリアルを見ながらToDoアプリを作った(2016/6/4)
↑の記事から始まり、本格的にSwiftに触れ3ヶ月経ち、今ではas
やら?
やら!
も読み取れるようになった。
というわけで、今一度基本に立ち返り、FizzBuzz
を題材にしてSwift(2.2)
を学んでいく。
FizzBuzzとは
1から100までの数字を見て、3で割り切れればFizz
、5で割り切れればBuzz
、両方で割り切れればFizzBuzz
、それ以外なら数字そのものを出力するというプログラム。元々は言葉遊びのゲームらしいが、私は1度もやったことがない。
素朴なFizzBuzz
for n in 1...100 {
if n % 15 == 0 {
print("FizzBuzz");
} else if n % 5 == 0 {
print("Buzz")
} else if n % 3 == 0 {
print("Fizz")
} else {
print(n)
}
}
FizzBuzzの説明をそのままコードで表現。
関数定義でFizzBuzz
func fizzbuzz(n:Int) -> String {
if n % 15 == 0 { return "FizzBuzz" }
if n % 5 == 0 { return "Buzz" }
if n % 3 == 0 { return "Fizz" }
return String(n)
}
for n in 1...100 {
print(fizzbuzz(n))
}
関数により数字をFizzBuzz化する処理(モデル)と出力する部分(ビュー)を分けている。
extensionでFizzBuzz
extension Int {
func fizzbuzz() -> String {
if self % 15 == 0 { return "FizzBuzz" }
if self % 5 == 0 { return "Buzz" }
if self % 3 == 0 { return "Fizz" }
return String(self)
}
}
for n in 1...100 {
print(n.fizzbuzz())
}
「数値を文字列にする関数」という考え方から「数値自身に、文字列化するメソッドを持たせる」というオブジェクト指向の考え方に進化。extension
は型を拡張する機能。SwiftでiOSアプリを書いていると、extension祭りになるほど強力だ。
getterでFizzBuzz
extension Int {
var fizzbuzz:String {
if self % 15 == 0 { return "FizzBuzz" }
if self % 5 == 0 { return "Buzz" }
if self % 3 == 0 { return "Fizz" }
return String(self);
}
}
for n in 1...100 {
print(n.fizzbuzz)
}
getterを用いてメソッド末尾の()
を取り除いた形。getterは変数のふりをしたメソッド。
subscriptでFizzBuzz
class FizzBuzz {
subscript (n:Int)->String {
if n % 15 == 0 { return "FizzBuzz" }
if n % 5 == 0 { return "Buzz" }
if n % 3 == 0 { return "Fizz" }
return String(n)
}
}
let fizzbuzz = FizzBuzz()
for n in 1...100 {
print(fizzbuzz[n])
}
subscript(添字定義)でメソッドを定義し、[]
にIndexを指定して配列のように結果を取得。subscriptによって、配列のふりをしたオブジェクトが作れる。
オブジェクト全体をイテレートしてFizzBuzz
extension FizzBuzz : SequenceType {
func generate() -> AnyGenerator<String> {
var n = 0
return AnyGenerator<String> {
if n == 100 {return nil}
n += 1
return self[n]
}
}
}
let fizzbuzz = FizzBuzz()
for s in fizzbuzz {
print(s)
}
for in
ループでイテレートさせるためにSequenceType
プロトコルに適合させる。map
やfilter
もできるようになる。ジェネリクスにはついてはまだあまり理解してない。
オプショナルでFizzBuzz
let fizzbuzz = [
3:"Fizz",5:"Buzz",6:"Fizz",9:"Fizz",
10:"Buzz",12:"Fizz",0:"FizzBuzz"
]
for n in 1...100 {
print(fizzbuzz[n % 15] ?? String(n))
}
連想配列を使用したFizzBuzzだが、print
する際オプショナルの性質を利用している。オプショナルは「値なしがあり得る型」で?? String (n)
の部分を削除すると、キーのあるところはOptional("")
、ないところはnil
と表示される。??
は左辺がnilなら、右辺の値という意味。fizzbuzz[n]
がオプショナル型ではなくStringだと、nに対応する値がない場合に困ってしまうのでオプショナルを利用する。
俺たちの戦いは続く
swift fizzbuzz
でググるとトップに出てくる下記記事のコードを見ても、何をやってるのかがわからなかった(fizzbuzzをしてるのはもちろんわかるのだが)Swiftマスターへ続く道はまだまだ長そうだ。
Swiftで関数型FizzBuzz
参考
Software Design Vol.2014/12 「小飼弾の書いて覚えるSwift入門」
SequenceTypeの利便性 in Swift 2.2