名前渡しパラメータ
基本
引数の定義時に「=>」をつけると名前渡しパラメータになる。どのようなものかは以下を参照
object Sample { def foo = { println("foo") 123 } /** 値渡し */ def byValue(a: Int) = { println("byValue entry") val r = a + a println("byValue exit") r } /** 名前渡し */ def byName(a: => Int) = { // =>をつけてるだけ println("byName entry") val r = a + a println("byName exit") r } def main(args: Array[String]) { println(byValue(foo)) println("") println(byName(foo)) } }
この実行結果は
foo byValue entry byValue exit 246 byName entry foo foo byName exit 246
両方ともfooを引数として渡しているが、
- 値渡しの場合は、評価された後の値が渡されており、その時にfooが一度だけ呼び出されている。
- 名前渡しの場合は、渡されるときには評価されず、必要なときに何度もfooが呼び出されている。
関数渡しとは異なる(らしい)
先のbyNameの定義を、明示的な「関数渡し」とすると、こうなる。
def byName(a:() => Int) = { println("byName entry") val r = a() + a() // 評価時にカッコが必要 println("byName exit") r }
そしてbyName呼び出し側もこう書く必要がある。
println(byName(() => foo))
※あるいは、「def foo」を「def foo()」にすればよい。
しかし、呼び出す関数に引数を与えたい場合にはこの書き方が必須である。つまり、
object Sample { def double(value: Int): Int = value * 2 def higher(f: (Int) => Int): Int = { f(123) } def main(args: Array[String]) { println(higher(double)) } }
結果は
246