9
8

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

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プロトコルに適合させる。mapfilterもできるようになる。ジェネリクスにはついてはまだあまり理解してない。

オプショナルで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

9
8
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
9
8

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?