Locked History Actions

Diff for "scala/ByNameParamter"

Differences between revisions 2 and 3
Deletions are marked like this. Additions are marked like this.
Line 75: Line 75:
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))
  }
}

名前渡しパラメータ

基本

引数の定義時に「=>」をつけると名前渡しパラメータになる。どのようなものかは以下を参照

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))

呼び出す関数に引数を与えたい場合にはこの書き方が必須である。つまり、

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))
  }
}