仙台iOS開発者勉強会(SWWDC) Advent Calendar 2014の22日目の記事です。
新しい言語を覚えるときによく作るのがWhiteSpaceのインタプリタです。以前は、ネットに上がっている問題やProject Eulerの問題を解いていたのですが、どうせだったら、作り終わったあとも使えるものはないかと思い、作り始めました。
WhiteSpaceの解説は、Wikiや公式、るびまを参考にして戴けると解りやすいと思います。
今回は、GoとSwiftでWhitespaceのインタプリタを作って言語により、作りやすかった点と難しかった点を2つにまとめてみました。
実際に作成したコードはこちら
文字列フィルタリング
whitespaceで有効な文字は、" "(半角スペース)、"\t"(タブ)、"\n"(改行)の3つです。
Goでは、オリジナルのデータを1byteずつ読み込み有効な3つの文字だったときは、新しい文字のスライス(配列)に保存する方法ととりました。
Swiftでは、filterメソッドを利用することで同じように有効な3つの文字を抽出できます。
個人的には、Swiftのfilterメソッドが使いやすく読みやすかったなと思いました。
func (inter *Interpreter) filter() {
for _, b := range inter.origin {
if bytes.IndexByte([]byte{Space, Tab, Lf}, b) >= 0 {
inter.source = append(inter.source, b)
}
}
}
init(code: [Character]) {
self.code = code.filter({
(c: Character) -> Bool in
return c == " " || c == "\t" || c == "\n"
})
}
配列(スライス)から任意文字数の取得
[Space]のStack操作命令や[Tab][Space]の計算処理のようにWhiteSpaceでは、使用する命令によって文字数が異なります。
Goで実装したときとSwiftで実装したときでは、実装方法が異なっているのですが、配列(スライス)から任意の文字数を取得する仕組みに差があったので、実装方法を別にしました。
Goの方は、添字に[n:m]を使って必要なデータを取得します。nは、取得する最初の位置、mが最後の位置です。
同じようにSwiftで実装しようと思ったのですが、方法が見つからず結果、switch case で実装していまいました。
func arithmetic(data []byte) (*Command, int, error) {
cmd := data[0:2]
switch {
case bytes.Compare(cmd, []byte{Space, Space}) == 0:
return newCommand("add"), len(cmd), nil
case bytes.Compare(cmd, []byte{Space, Tab}) == 0:
return newCommand("sub"), len(cmd), nil
case bytes.Compare(cmd, []byte{Space, Lf}) == 0:
return newCommand("mul"), len(cmd), nil
case bytes.Compare(cmd, []byte{Tab, Space}) == 0:
return newCommand("div"), len(cmd), nil
case bytes.Compare(cmd, []byte{Tab, Tab}) == 0:
return newCommand("mod"), len(cmd), nil
}
return nil, 0, fmt.Errorf("not defined command [%s]", "arithmetic")
}
func run() {
for c in code {
switch c {
case " ":
stackFunc()
break
case "\n":
flowControl()
break
case "\t":
switch code.advance()! {
case " ":
calcFunc()
break
case "\t":
heapFunc()
break
case "\n":
consoleFunc()
break
default:
println("error: not found command")
return
}
break
default:
println("error: not found command")
return
}
}
}
switch文が多くなってしまったので、今後改善するとすれば、switch文を使わない実装に変更していきたいと考えています。
最後に
iOSに関連して Swift を使ってどんな実装方法があるのかGOと比較してみました。
GOも1.4になってAndroidに対応したようで、今後は、Goを使ってAndroidやサーバーアプリを、Swiftを使ってiOSアプリを実装していければよいなと思った2014年の年でした。
クリスマスまであと3日風邪にお気をつけて元気にお過ごしください!