Yokohama.groovy #2 で GString にハマった話

2012/08/20 Yokohama.groovy #2 #yokohamagroovy #twitgroovy - Togetterまとめ

第2回 Yokohama.groovy をやってきました。

今回も会場はタネマキさん。
夜なのでビール片手に、総勢 4 人で開始です。

今回の範囲は、「3.4 プロパティ/フィールド/メソッドの参照方法」と「3.5 データ型」を中心に、写経して実行結果を確認しながら読み進めました。

プログラミングGROOVY

プログラミングGROOVY

話したことなど

  • 省略できたり、違う書き方ができたりすることが多くて便利
    • メソッドの引数の型とかゲッターセッターとか
    • 複数の人で開発する場合は、なんかルールが必要かも
    • CodeNarc 使いましょう
  • 真偽値判定は ==false じゃなくて ! を使う
  • GString 難しい
    • 遅延評価のところではまる

そんな感じでやっていたら、いつの間にか、@kyon_mm さんや @irof さんが Twitter で参加(?)してくれてました。

そして GString でハマる

今回の一番ハマりポイントはGStringでした。
最初は、Linux コマンドとかでもあるような、変数が展開されて文字列が取り出せるんだなと読み流していました。
ところが、リスト3.33 で (D) になる理由がよくわからずもやっとしてしまい、みんなであーでもないこーでもないと悩んでました。

特に本文中の、"GString の遅延評価的な性質を活かすためには、Imutable ではない値(配列やリストなど)を保持させ、GString のまま持ち回すようにします" という表現に惑わされてたような気がします。
"GString のまま" とか言われると、Imutable な値を展開したら GString じゃなくなるみたいに見えませんか?私だけですかね?

list=['x']

def gs = "$list ${list[0]}" //(A)

assert gs instanceof GString

assert gs == "[x] x" //(B)

list[0]='y' //(C)

assert gs == "[y] x" //(D)

ありがたいことに、@kyon_mm さんと @irof さんが色々説明してくれたおかげで理解が進みました。
@irof さんのサンプルコードがとても参考になりました。


GStringの評価が遅延されてるように見えるケースの · GitHub


今のところ、私はこのように理解しました。

  • def gs = "$list ${list[0]}" //(A)
    • $list は、変数 list の参照を保持している
      • list は、List 型であり mutable
    • $list[0] は、list[0] に格納されている値 'x' (String型のインスタンス)の参照を保持している
      • 'x' は String 型であり imutable
  • list[0]='y' //(C)
  • assert gs == "[y] x" //(D)
    • $list は、変数 list の参照なので、展開すると [y]
    • $list[0] は、(A) の時点で、 'x' の参照となっているので展開しても x のまま
  • @irof さんのサンプル 3.groovy
    • 13,14 行目で $list が変わらないのは、変数 list のインスタンスが変わったため
    • GString は設定された参照を変えられない

その他

集まって話しながらという形式は、一人で読んでいた時には気にならなかった点に気づくことができていいですね。

参加された方々、@kyon_mm さんと @irof さん、ありがとうございました。