teruroom's diary

ほぼ 8歳602ヶ月‏ の てるるーむ のプログラミングダイアリー

クロージャ~関数内のスコープにある引数以外の変数を参照できる関数~

 関数内の変数の参照は通常、引数を介して行います。ところが引数を介さずにある関数のスコープ内の変数を参照できる関数を定義することができます。これを クロージャ といいます。
 引数を介さずに関数内の変数を参照するためには通常はアクセッサメソッドであるgetter()を使います。しかし、クロージャはアクセッサメソッドを介さずに関数内のある変数を参照することができるのです。

 それでは、クロージャーの具体例をサンプルでみてみましょう。

  • 関数ストップウォッチ()の定義

 以下のコード例では、引数のない関数ストップウォッチ()を定義しています。この関数内のスコープに可変変数カウンターを宣言し、初期値として 0 を格納しています。このカウンターは外部から参照することはできません。
 しかし、この関数は引数のない無名関数を返す処理を行っています。この無名関数がクロージャです。

 具体的にはこのクロージャには名前がなくて引数もないので「()」のように記述しています。そうして、このクロージャの処理を「」記号の右辺に記述しています。処理は可変変数 カウンター の値を1インクリメントすることです。
 さらに、このクロージャの戻り値は可変変数 カウンタ になります。Scalaでは関数の最後の式や値が評価されてそのまま戻り値になります。したがって、このクロージャの戻り値は可変変数 カウンタ になります。
 これで、関数ストップウォッチ()内の可変変数 カウンタ が参照できました。

  • 関数を利用して可変変数 カウンタ の参照

 まず、関数 ストップウォッチ() を不変変数計測に代入します。不変変数計測クロージャー()を呼び出すたびに可変変数 カウンター がインクリメントされて1づつ値が増えていきます。実行結果は以下のようになります。

object Main extends App {
  def ストップウォッチ() = {
    var カウンタ = 0
    () ⇒ カウンタ += 1 ; カウンタ
  }

  val 計測 = ストップウォッチ()
  print( 計測() + "秒 : " )
  print( 計測() + "秒 : " )
  print( 計測() + "秒 : " )
  print( 計測() + "秒 : " )
  print( 計測() + "秒 : " )
}
  • 実行方法
> scala ストップウォッチ.scala
  • 実行結果
> 1秒 : 2秒 : 3秒 : 4秒 : 5秒 :

 以下のWebサービスで動作を確認してみてください。

https://paiza.io/projects/X-nwb6dyTrfhjfLfecK-EQ