書いて覚えるSwift入門

第0回One More Thing for Developers

Introducing Swift

WWDC2014で⁠One More Thing⁠として発表された新プログラミング言語Swift。本連載に間に合うかどうかやきもきしていたのですが、2013年10月19日、Xcode 6.1からBetaが取れてぎりぎり間に合いました注1・図1⁠。

図1 Swiftリリース紹介ページ
図1 Swiftリリース紹介ページ

どんな言語でしょうか。Apple は[Introducing Swift]でこう紹介しています。

Swift is an innovative new programming language for Cocoa and Cocoa Touch. Writing code is interactive and fun, the syntax is concise yet expressive, and apps run lightning-fast. Swift is ready for your next iOS and OS X project―or for addition into your current app―because Swift code works side-by-side with Objective-C.

弾訳
⁠SwiftはCocoaおよびCocoa Touch用の革新的新言語です。コードを書くのはインタラクティブで楽しく、文法は簡潔ながら表現力が高く、アプリは超高速で動きます。SwiftはiOSおよびOS Xでいますぐ利用可能で、Objective-Cと並存可能なので、既存のアプリへの追加もできます」

この口上だけ見ると、SwiftはiOS/OS Xアプリ開発専用に見えますが、専用にしておくにはもったいないほどよくできた言語で、学べば学ぶほど汎用向けの言語であることが明らかになってきます。Swiftをオープンソース化するつもりがあるかを、Appleはつまびらかにしていませんが、同社のオープンソース戦略、とくにLLVM(Low Level Virtual Machine)へのコミットメントを考えるとその可能性は低くないと筆者は考えています。

本連載では、Swiftを汎用言語として扱います。よってiOS/OS X固有な点は極力排除し、言語そのものにフォーカスします。JavaScriptで言えば、WebブラウザだけでなくNode.jsでも動くように書く、といったところでしょうか。

Shut the F?ck up and Write Some Code!

読者の皆さんは、新言語を学ぶときどうされているでしょうか? 仕様書を徹頭徹尾読む? それもいいでしょう。実際Apple自身がバイブルに相当するThe Swift Programming LanguageをiBooksで無料公開しています。

しかし処理系であるXcodeも、Mac App Storeで無料公開されているのです。つまりMacさえ持っていれば、追加費用は一切かからないということ。Apple自身、インタラクティブであることをSwiftの売りにしているのです。これは書かずにいられませんよね。

とりあえずFizzBuzz

というわけで、何か書いてみましょう。何を書くのがいいか。FizzBuzzとか。

本誌の読者であれば、FizzBuzzが何かはご存じだと思いますが、念のため紹介しておくと、1から100までの数字を見て、3で割り切れれば⁠Fizz⁠⁠、5で割り切れれば⁠Buzz⁠⁠、両方で割り切れば⁠FizzBuzz⁠⁠、それ以外なら数字そのものを出力するという簡単なプログラムです。とりあえずこの説明のまま書き下してみましょうかリスト1⁠。

リスト1 とりあえず⁠FizzBuzz”
for n in 1...100 {
    if n % 15 == 0 {
        println("FizzBuzz")
    } else if n % 5 == 0 {
        println("Buzz")
    } else if n % 3 == 0 {
        println("Fizz")
    } else {
        println(n)
    }
}

このコード片を、そのままplaygroundに打ち込んでみましょう図2⁠。

図2 playgroundにリスト1を入力!
図2 playgroundにリスト1を入力!

たしかに仕様どおりに動いているようです。

ここで、まったく同じことを、Javaでやってみましょう(①~③⁠⁠。

  • リスト2の内容のFizzBuzz.javaを作成する
  • ② javac Fizzbuzz.javaコンパイルする
  • ③ java FizzBuzzで実行する
リスト2 FizzBuzz.java
public class FizzBuzz {
    public static void main(String[] args) {
        for (int i=1; i<=100; i++) {
           if (i % 15 == 0) {
                System.out.println("FizzBuzz");
            } else if (i % 3 == 0) {
                System.out.println("Fizz");
            } else if (i % 5 == 0) {
                System.out.println("Buzz");
            } else {
                System.out.println(i);
            }
        }
    }
}

同じことをするのにも、ずいぶんと「おまじない」が多いことに気づきます。プログラム本体は、public Class FizzBuzzpublic static void main(String[] args)でくるまなければならないですし、ファイル名もFizzBuzz.javaでなければならないですし、さらにjavacでコンパイルしてjavaで実行しなければなりません。コードの部分はほとんど同じなのに、やらなければならないことのいかに多いことか。

「簡単なことは簡単に。難しいこともそれなりに」とは、プログラミング言語Perlの父、Larry Wallの言葉ですが、Swiftもまた「簡単なことは簡単に」書けるプログラミング言語であるようです。

MVCは分けましょう

しかし手練れのプログラマであれば、モデルとビューが渾然一体となった上記のようなプログラムはクソコードに感じられるのではないでしょうか。数字をFizzBuzz化する部分とFizzBuzzを出力する部分は分けたいはずです。

そうするにはどうしたらよいでしょう。そう。関数ですねリスト3⁠。

リスト3 Swiftで⁠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 {
    println(fizzbuzz(n))
}

Swiftもほかのプログラミング言語同様、関数を定義することができます。宣言はfunc。PerlのsubやRubyのdefより1文字多いですが、JavaScriptのfunctionの半分。ただし型は宣言しなければなりません。引数は数値のInt。戻り値は文字列のString。そう。SwiftはCやC++やJava同様、静的なコンパイル言語なのです。しかし最初の例では型宣言は出てきません。必要ないかぎり、型は推論されるからです。

オブジェクト(思考|志向|嗜好)

「数値を文字列にする関数」というのは、多くの言語で用いられている考え方です。が、オブジェクト指向ではこう考えます。⁠数値自身に、文字列化するメソッドを持たせる⁠⁠。Rubyならリスト4でしょうか。Swiftなら、リスト5のようになります。

リスト4 Rubyで⁠FizzBuzz”
class Fixnum 
  def fizzbuzz() 
    if self % 15 == 0 then return "FizzBuzz" end 
    if self % 5 == 0 then return "Buzz" end 
    if self % 3 == 0 then return "Fizz" end 
    return self.to_s 
  end
end

(1..100).each do ¦n¦ 
  puts n.fizzbuzz
end
リスト5 Swiftで⁠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 {
    println(n.fizzbuzz())
}

Rubyでは新たなクラスを定義するときも、既存のクラスを拡張するときもclassですが、Swiftでは既存の型を拡張するときにはextensionを使います。何をしているのかこちらのほうがわかりやすいです。

しかしRubyと比べると、メソッド末尾の()が不恰好というか括弧が余計に見えます。これを取り除くことはできないでしょうか? ――できます。リスト6を見てください。

リスト6 Swiftで⁠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 {
  println(n.fizzbuzz)
}

変数のふりをしたメソッドをゲッター(getter)といいますが、Swiftのゲッターは関数の中身はそのままで宣言だけが変わっています。ずいぶんと直感的です。

ところでRubyでは、配列のふりをしたオブジェクトも作れます。そういうオブジェクトを定義するには[]という名前のメソッドを定義してしまえばよいのです。Swiftではどうでしょうか? ――はい。これも、できます。リスト7を見てください。[]ではなくsubscriptですが。

リスト7 Swiftで⁠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 {
    println(fizzbuzz[n])
}

しかし添字のふりをした引数だけではまだ十分配列とは言えません。RubyのEnumerableのように、オブジェクト全体をイテレートすることはできるのでしょうか。――もちろん。リスト8を見てください。Swiftならできます。

リスト8 Swiftで⁠FizzBuzz⁠(オブジェクトをイテレート)
// class FizzBuzz { ... } はそのまま
extension FizzBuzz : SequenceType {
    func generate() -> GeneratorOf<String> {
        var n = 0
        return GeneratorOf<String> {
            if n == 100 { return nil }
            return self[++n]
        }
    }
}
let fizzbuzz = FizzBuzz()
for s in fizzbuzz {
    println(s)
}

nilほどオプショナル

ところでSwiftに関してググってみると、Optionalという単語がいっぱい出てきます。――Rubyのパパもこういってます

「a language for the rest of us」の観点から言うとSwiftのoptional型は大変素晴らしい

実際に見てみましょう。今度は「配列のふりをしたオブジェクト」ではなく、連想配列を使ってFizzBuzzしてみますリスト9⁠。

リスト9 Swiftで⁠FizzBuzz⁠(連想配列)
let fizzbuzz = [
    3:"Fizz",5:"Buzz",6:"Fizz",9:"Fizz",
    10:"Buzz",12:"Fizz",0:"FizzBuzz"
]
for n in 1...100 {
    println(fizzbuzz[n % 15] ?? String(n))
}

たしかにきちんと動いているようですが、これのどこがオプショナルなのでしょう? リスト9のコードから?? String(n)を削除してみてください。どうなりましたか? 連想配列のキーがあるところはOptional("")ないところはnilと表示されたはずです。

ここで、fizzbuzz[n]の型を考えてみましょう。単にStringだと、nに対応する値がない場合に困ってしまいます。Optionalは、まさにこういうときのためにあります。⁠値なしがあり得る型」を表現できるのです。HaskellでいうところのEitherですね。

これで、??の意味が見えてきました。⁠左辺が『値なし』なら、右辺の値」という意味に違いありません。この「値なし」は、SwiftもRubyをはじめとする多くの言語と同様、nilという名前がついています。

次回予告

ここまで、FizzBuzzを肴に駆け足でSwiftを見てきました。JavaっぽくもありRubyっぽくもある。Jony IveはiOS 7の紹介で⁠While iOS 7 is completely new, it is important to us to make it instantly familiar.⁠とのたまいましたが、Swift もcompletely newにしてinstantly familiarな言語という点で実にAppleらしい。

しかしSwiftの⁠instantly familiar⁠はオブジェクト指向にとどまりません。次回は関数型言語としてのSwiftを見ていきます。

Software Design

本誌最新号をチェック!
Software Design 2022年9月号

2022年8月18日発売
B5判/192ページ
定価1,342円
(本体1,220円+税10%)

  • 第1特集
    MySQL アプリ開発者の必修5科目
    不意なトラブルに困らないためのRDB基礎知識
  • 第2特集
    「知りたい」⁠使いたい」⁠発信したい」をかなえる
    OSSソースコードリーディングのススメ
  • 特別企画
    企業のシステムを支えるOSとエコシステムの全貌
    [特別企画]Red Hat Enterprise Linux 9最新ガイド
  • 短期連載
    今さら聞けないSSH
    [前編]リモートログインとコマンドの実行
  • 短期連載
    MySQLで学ぶ文字コード
    [最終回]文字コードのハマりどころTips集
  • 短期連載
    新生「Ansible」徹底解説
    [4]Playbookの実行環境(基礎編)

おすすめ記事

記事・ニュース一覧