GoでScalaっぽくコレクション操作できるメソッドを作ってみる。

[ただの集団 Advent Calendar 2018](https://adventar.org/calendars/3447)の14日目です。
昨日は、takahiro.haginoさんの[auto-join-overview](https://haginot.github.io/auto-join/auto-join-overview.html)でした。
私は、一応このアドベントカレンダーの発起人ですが、ランダム関数により、14日目という貴重な日程を頂きました😉
[ただの集団のイチロー](https://adventar.org/calendars/3447#list-2018-12-01)さんのおかげで素敵なメンバーが集まってくれました🙏

# はじめに
プログラミングを始めてから、一番長い間触れてきていたのがScalaだった私ですが、業務で新しいアプリケーションの作成の際にGo言語を採用することになりました。
Goを書いていても、Scalaのように簡単に、配列(正確にはスライス)の操作がしたいと思ったことがきっかけでこの記事を書いています。

欲しいと思ったメソッドをScalaと比較しつつ羅列して行きます💪

# gotour
簡単にGo言語の動作確認をしたい時におすすめのwebサービスです。ただ、サーバーが混み合うことがあるので、OSS版の方をgetすることをおすすめします！
https://github.com/atotto/go-tour-jp

```
$ go get github.com/atotto/go-tour-jp/gotour
$ gotour
```

## map
今回はmapMethodとして実装。(mapは予約語だった)

```Scala:map.scala
val list: Seq[Int] = Seq(1, 2, 3, 4, 5)
val mapedList = list.map(_ * 2)
println(mapedList)
// 出力: Seq(2, 4, 6, 8, 10)
```

```golang:mapFunction.go
package main
import "fmt"

type anyList []int
func main() {
    var numberList anyList = []int{1, 2, 3, 4, 5}
    mapedList := numberList.mapMethod(func(i int) int {
        return i * 2
    })
    fmt.Println(mapedList)
}

func (list anyList) mapMethod(f func(int) int) anyList {
    var acc anyList
    for _, l := range list {
        acc = append(acc, f(l))
    }
    return acc
}
// output: [2 4 6 8 10]
```
## filter

```Scala:filter.scala
val list: Seq[Int] = Seq(1, 2, 3, 4, 5)
val filteredList = list.filter(_ % 2 == 0)
println(filteredList)
// output: Seq(2, 4)
```

```golang:filter.go
package main
import "fmt"

type anyList []int
func main() {
    var numberList anyList = []int{1, 2, 3, 4, 5}
    filteredList := numberList.filter(func(i int) bool {
        return i % 2 == 0
    })
    fmt.Println(filteredList)
}

func (list anyList) filter(f func(int) bool) anyList {
    var acc anyList
    for _, l := range list {
        if f(l) {
            acc = append(acc, l)
        } 
    }
    return acc
}
// output: [2 4]
```

## contains

```Scala:contains.scala
val list: Seq[Int] = Seq(1, 2, 3, 4, 5)
val isTwo = list.contains(2)
val isOneHundred = list.contains(100)
if (isTwo) {
     println("このリストには、2が含まれています。")
 } else {
     println("このリストには、2が含まれていません。")
 }
 if (isOneHundred) {
     println("このリストには、100が含まれています。")
 } else {
     println("このリストには、100が含まれていません。")
 }

 /** output:
このリストには、2が含まれています。
このリストには、100が含まれていません。
*/
```

```golang:contains.go

package main
import "fmt"

type anyList []int
func main() {
    var numberList anyList = []int{1, 2, 3, 4, 5}
    if numberList.contains(2) {
        fmt.Println("このリストには、2が含まれています。")
    } else {
        fmt.Println("このリストには、2が含まれていません。")
    }
    if numberList.contains(100) {
        fmt.Println("このリストには、100が含まれています。")
    } else {
        fmt.Println("このリストには、100が含まれていません。")
    }
}

func (list anyList) contains(target int) bool {
    for _, n := range list {
        if n == target {
            return true
        } 
    }
    return false
}

/** output:
このリストには、2が含まれています。
このリストには、100が含まれていません。
*/
```

## exists

```Scala:exists.scala
val list: Seq[Int] = Seq(1, 2, 3, 4, 5)
val hasEvenNumber = list.exists(_ % 2 == 0)
if (hasEvenNumber) {
	println("numberLisrは偶数を含んでいます。")
} else {
	println("numberListは偶数を含んでいません。")
}
// output: numberLisrは偶数を含んでいます。
```

```golang:exists.go
package main
import "fmt"
type anyList []int
func main() {
    var numberList anyList = []int{1, 2, 3, 4, 5}
    hasEvenNumber := numberList.exists(func(i int) bool {
        return i % 2 == 0
    })
    if hasEvenNumber {
        fmt.Printf("numberListは偶数を含んでいます。")
    } else {
        fmt.Printf("numberListは偶数を含んでいません。")
    }
}

func (list anyList) exists(f func(int) bool) bool {
    for _, l := range list {
        if f(l) {
            return true
        } 
    }
    return false
}
// output: numberLisrは偶数を含んでいます。
```

# まとめ
それぞれの言語にはその言語の良さがあります。今回はそこを無視して、自分の書きたいようにかけるかの挑戦でした。非常に楽しかったです。