GStringは遅延評価か?
GStringが遅延評価かどうかが話題になっているようです:
http://genzou-postit.blogspot.com/2009/06/gstring.html
「Groovyイン・アクション」をお持ちの方はp.409の13.2.5を読んでみてください。以下、自分の理解をまとめてみます:
- GString内のプレースホルダ(${〜}の部分)の中の式はただちに評価される
- GStringオブジェクトは、この評価結果(式の値)として返されたオブジェクトへの参照をそのまま保持しておく
- GStringオブジェクト自体が文字列化されるタイミングで、保持している各プレースホルダの評価結果オブジェクトも文字列化される
つまり、
- プレースホルダ内の式の評価はeagerに行われる
- 式の値の文字列化はlazyに行われる
ということです(ちょっとややこしいけど)。
というわけで、式の値が文字列や数値などimmutableな場合は遅延評価には見えませんが、リストやStringBufferなどの変更可能なオブジェクトの場合は、GString構築後にそのオブジェクトを変更すると、GStringの文字列化結果にも反映される(遅延評価に見える)ことになります。
例1:式の値がimmutableなオブジェクトの場合
i=1 gs="$i" // gsにはiが指す1という数値オブジェクトへの参照が保持される ++i // iをいじっても数値オブジェクト1自体が変更されるわけではない assert gs == "1" // iの操作はgsの文字列表現には影響しない
例2:式の値が変更可能なオブジェクトの場合
l=[1] gs="$l" // gsにはlが指す[1]というリストオブジェクトへの参照が保持される l<<2 // l経由でリストオブジェクト自体が変更される assert gs == "[1, 2]" // lの操作がgsの文字列表現に反映された
以上、なんか間違ってたらご指摘ください。