関数の内側から外側のスコープの変数にアクセスできるかどうか
Java 2015/02/25
Java8ではメソッド内にラムダ式を書くことができるようになったが、 Java7までは、メソッド定義の中に関数を書くことはできない。ただ、メソッド定義の中に内部クラスとそのメソッドを書くことはできる。
その内側のメソッド(内部クラスのメソッド)からは、外側のメソッドの変数を参照することはできるが、変数の書き換えをすることはできない。
Java7までは、その変数が final
で指定されている必要がある。
Java8からは、final
指定がなくてもよいが、実質 final
である必要がある。つまり、その変数がどこからも書き換えられていないことが必要である。
Java8からはラムダ式を書けるが、外側の変数を書き換えられないのは同じである。
PHP 2013/11/16
function builder(){
$i = 0;
return function() use (&$i) {
echo "$i\n";
$i++;
};
}
$f1 = builder();
$f2 = builder();
$f1(); // => 0
$f1(); // => 1
$f2(); // => 0
$f1(); // => 2
関数の外側のスコープにある変数を参照するには use ($i)
のように宣言する必要がある。さらにその変数を書き換えるには use (&$i)
のように宣言する必要がある。
上記の例で use (&$i)
を use ($i)
と書くと、$i++
でエラーは発生しないが、書き換えた結果は無視され、4回とも0
が出力される。
use
を書かなかった場合は $i
を参照できないので、
PHP Notice: Undefined variable: i
が出力される。
Ruby 2013/06/09
def builder
i = 0
Proc.new do
puts i
i = i + 1
end
end
f1 = builder
f2 = builder
f1.call # => 0
f1.call # => 1
f2.call # => 0
f1.call # => 2
Procオブジェクトは、その外側の変数を読み書きできる。
JavaScript 2013/09/12
関数の中から外にある変数を読み書きできる。
var builder = function(){
var i = 0;
return function(){
console.log(i);
i = i + 1;
}
}
var f1 = builder();
var f2 = builder();
f1(); // => 0
f1(); // => 1
f2(); // => 0
f1(); // => 2