GoとSwiftを比較して使いやすかったとこと使いにくかったところのまとめ


[仙台iOS開発者勉強会(SWWDC) Advent Calendar 2014](http://qiita.com/advent-calendar/2014/iosendai)の22日目の記事です。

新しい言語を覚えるときによく作るのが[WhiteSpace](http://compsoc.dur.ac.uk/whitespace/index.php)のインタプリタです。以前は、ネットに上がっている問題や[Project Euler](http://odz.sakura.ne.jp/projecteuler/)の問題を解いていたのですが、どうせだったら、作り終わったあとも使えるものはないかと思い、作り始めました。
WhiteSpaceの解説は、[Wiki](http://ja.wikipedia.org/wiki/Whitespace)や[公式](http://compsoc.dur.ac.uk/whitespace/index.php)、[るびま](http://magazine.rubyist.net/?0022-Legwork)を参考にして戴けると解りやすいと思います。

今回は、GoとSwiftでWhitespaceのインタプリタを作って言語により、作りやすかった点と難しかった点を２つにまとめてみました。


実際に作成したコードはこちら

- [Swift](https://gist.github.com/205544f1fd29482f063d.git)
- [Go](https://github.com/135yshr/wspacego)


# 文字列フィルタリング
whitespaceで有効な文字は、" "(半角スペース)、"\t"(タブ)、"\n"(改行)の３つです。

Goでは、オリジナルのデータを１byteずつ読み込み有効な３つの文字だったときは、新しい文字のスライス（配列）に保存する方法ととりました。
Swiftでは、filterメソッドを利用することで同じように有効な３つの文字を抽出できます。
個人的には、Swiftのfilterメソッドが使いやすく読みやすかったなと思いました。

```interprinter.go
func (inter *Interpreter) filter() {
	for _, b := range inter.origin {
		if bytes.IndexByte([]byte{Space, Tab, Lf}, b) >= 0 {
			inter.source = append(inter.source, b)
		}
	}
}
```

```CodeStack.swift
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 で実装していまいました。

```converter.go
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")
}
```

```Wspace.swift
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日風邪にお気をつけて元気にお過ごしください！