groovysh では def は使わないほうがいい
id:fumokmm さんが書かれていた
groovyshではdefは使わないほうがいい(たぶん)が気になったので、それが 『たぶん』 ではなく 『真実』 であることを書いてみた。
検証環境は Groovy 1.7.5, JVM: 1.6.0_20
真実 その 1...
groovysh は実行単位で インスタンスが異なる。
groovy:000> this; ===> groovysh_evaluate@20dccfab groovy:000> this; ===> groovysh_evaluate@2e831a91
真実 その2...
宣言した変数は インスタンス変数ではない。
→ 他のインスタンスからは読み取れない。
groovy:000> def a = 0; this.a; ERROR groovy.lang.MissingPropertyException: No such property: a for class: groovysh_evaluate at groovysh_evaluate.run (groovysh_evaluate:2) ...
上記の例外を見る限り 変数 a は groovysh_evaluate.run() のローカル変数だと思われる。
と言うことで...
def で宣言した変数は 同じ行 (実行) でしか参照できない。
ではなぜ def を使わない場合は
groovy:000> a = 10 ===> 10 groovy:000> a ===> 10のように 2回目の実行でも 変数 a が参照できるのだろうか?
真実 その3...
def をつけずに宣言した変数は binding される。(詳細は こちら)
→ binding された変数は 同一 Shell 内で参照できる。
groovy:000> a = 10 ===> 10 groovy:000> binding['a'] ===> 10 groovy:000> binding.variables.each { if (it.key ==~ /^a.*/) println it } a=10
更に、id:orangecloverさんが書かれた
Groovyでdef関数からdef関数が呼び出せないのか?というのも この binding が関係している。
真実 その4...
メソッドもクロージャも binding される。
→ 同一 Shell 内であれば 呼び出せる。
groovy:000> void a1() { println a } ===> true groovy:000> def a2() { println a } ===> true groovy:000> a3 = { println a } ===> groovysh_evaluate$_run_closure1@41e8e144 groovy:000> binding.variables.each { if (it.key ==~ /^a.*/) println it } a=10 a1=org.codehaus.groovy.runtime.MethodClosure@190872ce a2=org.codehaus.groovy.runtime.MethodClosure@79a93f38 a3=groovysh_evaluate$_run_closure1@41e8e144
真実 その5...
メソッド内では binding 変数が参照できない。
→これは 不具合っぽいけど...
groovy:000> a1(); ERROR groovy.lang.MissingPropertyException: No such property: a for class: groovysh_evaluate at groovysh_evaluate.a1 (groovysh_evaluate:2) at groovysh_evaluate.run (groovysh_evaluate:2) ... groovy:000> a2(); ERROR groovy.lang.MissingPropertyException: No such property: a for class: groovysh_evaluate at groovysh_evaluate.a2 (groovysh_evaluate:2) at groovysh_evaluate.run (groovysh_evaluate:2) ...