Scalaでのメソッド呼び出しの書き方一覧と推奨される書き方


# メソッド呼び出しの基本形はJavaと同じ

```scala
  オブジェクト.メソッド(引数１, 引数２...)
```

# メソッド呼び出しの書き方一覧

先ずは非推奨な書き方も含めて呼び出せる全ての形式をコードに書いてみる。
`////`でコメントアウトしてある行は使用できない形式になる。

```scala
class Hoge {
  //引数リストがないメソッド
  def f1 = 1
  //引数がないメソッド
  def f2() = 1
  //引数が１つのメソッド
  def f3(x: Int) = x * 2
  //引数が複数のメソッド
  def f4(x: Int, y: Int) = x * y
}

//引数リストがないメソッド
////hoge.f1()
////hoge f1()
hoge.f1                                           //> res0: Int = 1
hoge f1                                           //> res1: Int = 1
//空行は伊達じゃないよ

//引数がないメソッド
hoge.f2()                                         //> res2: Int = 1
hoge.f2                                           //> res3: Int = 1
hoge f2()                                         //> res4: Int = 1
hoge f2                                           //> res5: Int = 1
//空行は伊達じゃないよ

//引数が１つのメソッド
hoge.f3(1)                                        //> res6: Int = 2
hoge f3(1)                                        //> res7: Int = 2
hoge f3 1                                         //> res8: Int = 2
hoge.f3 { 1 }                                     //> res9: Int = 2
hoge f3 { 1 }                                     //> res10: Int = 2
////hoge.f3 1

//引数が複数のメソッド
hoge.f4(1, 2)                                     //> res11: Int = 2
hoge f4(1, 2)                                     //> res12: Int = 2
////hoge.f4 1, 2
////hoge f4 1, 2
```

* 引数リストがないメソッドは`()`を付けて呼び出すことはできない。
* 引数が１つのメソッドは`()`の代わりに`{}`を使うことができる。
* `.`は省略できる。
* 引数がないメソッドは`()`を省略できる
* 引数が１つのメソッドでも`()`を省略できるが、この場合`.`も同時に省略しなければならない。

# 用語説明

推奨される書き方を説明する前に、その中で使用する用語について少し説明しておく。

## 中置記法

引数が１つのメソッドで`.`と`()`を省略した形式を中置記法という。

```scala:中置記法の形式
オブジェクト メソッド名 引数
```

## 後置記法

引数リストがないメソッドと引数がないメソッドで`.`と`()`を省略した形式を後置記法という。

```scala:後置記法の形式
オブジェクト メソッド名
```
後置記法は行末でしか使えない。
また、次の行は空行にしなければならない。

## 副作用

呼び出した時に戻り値以外に何らかの影響を与えるメソッドを「副作用があるメソッド」という。

* java.util.Listのclear()メソッドはListオブジェクトの状態を変更するので「副作用があるメソッド」
* java.util.Listのsize()メソッドはListオブジェクトの状態を変更しないので「副作用がないメソッド」
* System.out.println()はコンソール出力を行うので「副作用があるメソッド」

# 推奨される書き方

`////`でコメントアウトしている行は推奨されない書き方。

## 引数がないメソッド
### 副作用がない場合は()を省略してもよい
```scala
val javaList = new java.util.ArrayList[Int]()     //> javaList  : java.util.ArrayList[Int] = []

javaList.size()                                   //> res13: Int = 0
javaList.size                                     //> res14: Int = 0
```

### 副作用がある場合は()を省略してはいけない
```scala
javaList.clear()
////javaList.clear
```

### 後置記法は原則使用しない
```scala
////javaList size
////javaList clear
```

## 引数が１つのメソッド
### 副作用があるメソッドは()を省略してはいけない
```scala
javaList.add(1)                                   //> res15: Boolean = true
////javaList add 1
```

### 副作用がない場合は中置記法で書いてもよい
```scala
javaList.indexOf(1)                               //> res16: Int = 0
javaList indexOf 1                                //> res17: Int = 0
```

### 演算子のように使うメソッドは中置記法で書いた方がわかりやすい
```scala
1.max(2)                                          //> res18: Int = 2
1 max 2                                           //> res19: Int = 2

0.to(3)                                           //> res20: scala.collection.immutable.Range.Inclusive = Range(0, 1, 2, 3)
0 to 3                                            //> res21: scala.collection.immutable.Range.Inclusive = Range(0, 1, 2, 3)

"abc".concat("def")                               //> res22: String = abcdef
"abc" concat "def"                                //> res23: String = abcdef
```

## 引数が複数のメソッド
### 副作用の有無に関係なく`.`は省略しない
```scala
javaList.add(0, 2)
javaList.subList(1, 2)                            //> res24: java.util.List[Int] = [1]
////javaList add(0, 2)
////javaList subList(1, 2)
```

## 関数を渡すメソッド
### 引数が１つのメソッドで関数を渡す場合は中置記法で{}を使ってもよい
```scala
val nums = Array(1, 2, 3)                         //> nums  : Array[Int] = Array(1, 2, 3)

nums.exists(_ < 0)                                //> res25: Boolean = false
nums exists { _ < 0 }                             //> res26: Boolean = false
```
### 処理が複数行になる場合は{}のほうがシンプルになる
```scala
nums.filter(i => {
	val tmp = i.toBinaryString
	tmp.exists(_ == '0')
})                                                //> res27: Array[Int] = Array(2)
nums.filter { i => 
	val tmp = i.toBinaryString
	tmp.exists { _ == '0' }
}
```

### 中置記法のメソッドチェインの最後では後置記法を使っても良い
```scala
nums.filter(_ >= 2).map(_ * 2).toList             //> res28: List[Int] = List(4, 6)
nums filter { _ >= 2 } map { _ * 2 } toList       //> res29: List[Int] = List(4, 6)
```

# どう書けばいいか迷った時

とりあえずJavaと同じ形式で書いとけ。非推奨ではないから。

# 参考

[Scalaスタイルガイド](http://yanana.github.io/scala-style/)
[Scalaメモ(Hishidama's Scala Memo)](http://www.ne.jp/asahi/hishidama/home/tech/scala/index.html)