Introducing Swift
WWDC2014で“ One More Thing” として発表された新プログラミング言語Swift。本連載に間に合うかどうかやきもきしていたのですが、2013年10月19日、Xcode 6.1からBetaが取れてぎりぎり間に合いました(注1・図1 ) 。
図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を入力!
たしかに仕様どおりに動いているようです。
ここで、まったく同じことを、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 FizzBuzz
とpublic 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を見ていきます。
第1特集
MySQL アプリ開発者の必修5科目
不意なトラブルに困らないためのRDB基礎知識
第2特集
「知りたい」「 使いたい」「 発信したい」をかなえる
OSSソースコードリーディングのススメ
特別企画
企業のシステムを支えるOSとエコシステムの全貌
[特別企画]Red Hat Enterprise Linux 9最新ガイド
短期連載
今さら聞けないSSH
[前編]リモートログインとコマンドの実行
短期連載
MySQLで学ぶ文字コード
[最終回]文字コードのハマりどころTips集
短期連載
新生「Ansible」徹底解説
[4]Playbookの実行環境(基礎編)