uehaj's blog

Grな日々 - GroovyとかGrailsとかElmとかRustとかHaskellとかReactとかFregeとかJavaとか -

Groovyの奇妙な演算子(その1)

Groovyの奇妙な演算子たちを簡単に紹介してみます。
「奇妙な」とは、とりあえずここでは「Javaに無い」という意味です。

今回は「その1」として以下を紹介します。

    ?.      *.      .@      .&

「?.」セーフナビゲーション演算子

「.」演算子と同様にメンバ(フィールド、メソッド、プロパティ)を参照するものですが、左辺がnullであった場合にもNullPointerExceptionが発生しません。左辺がnullであった場合、値として単にnullが得られます。

【覚え方】

foo?.barは、((foo == null) ? null : foo.bar )と解釈されます。このときの?と.を思い出しましょう。

【classic groovyな人への注記】

昔は->と表記していました。

「*.」コレクションの要素それぞれのメンバをリストにしたものを返す演算子

一般に、

<コレクション>*.<メンバ>

は、

<コレクション>.collect{ it.<メンバ> }

と等価です。たとえば、["a","ab","abc"]*.length()は、"a".length(), "ab".length(), "abc".length()をリストにしたもの、すなわち[1,2,3]を返します。

groovy> ["a","ab","abc"]*.length()
groovy> go

===> [1, 2, 3]

*.はマップに対しても適用できます。

groovy> [ [name:"taro", age:13], [name:"hanako", age:15] ]*.age
groovy> go

===> [13, 15]

【覚え方】

*は集合中の「任意の要素」をあらわしていて、それに適用(.)している、とか。

「.@」XmlSlurperでパースしたXMLノードの属性を指定する演算子

groovy> xml = new XmlSlurper().parseText('<hoge><a href="URL">AAA</a></hoge>')
groovy> xml.a.@href
groovy> go

===> URL

groovy> xml.a['@href']
groovy> go

===> URL

groovy> xml.a.'@href'
groovy> go

===> URL

XmlParserでパースした時の結果に対しては(今のところ)機能しないようです。

【覚え方】

XPathの記法と同じ(XMLの属性は@をつけて参照する)。

【参考URL】

http://groovy.codehaus.org/GPath

「.&」オブジェクトインスタンスが持つメソッドクロージャを取り出す演算子

Groovyでは、メソッドとクロージャして実現されているわけですが、は異なりますが、メソッドからクロージャを生成することが出来ます。.&はそれをおこなう演算子です。

groovy> class c {
groovy> void method() { println "hello"; }
groovy> def method = 3
groovy> }
groovy> a = new c();
groovy> go

===> c@16dadf9

groovy> a.method()
groovy> go
hello

===> null

groovy> a.method
groovy> go

===> 3

groovy> p = a.method
groovy> go

===> 3

groovy> p
groovy> go

===> 3

groovy> p = a.&method
groovy> go

===> org.codehaus.groovy.runtime.MethodClosure@176cad3

groovy> p()
groovy> go
hello

このように、.&で、特定のインスタンスに結びついたクロージャが取れます。関数ポインタやdelegateとは違います。もっと素朴なもの。

【classic groovyな人への注記】

昔は、単に「.」でメソッドクロージャが取れましたが、同名のプロパティが存在したときにあいまいなのでこのような専用の演算子ができたようです。

まとめ

以上の様に、Groovyにはリストや集合に対する高機能な演算子が追加されており、時にはRuby以上に簡潔な記述が可能です。「わかりやすいかどうか」には疑念もなくはないですが、「覚え方」などを工夫することで、なんとかなるのではないかと。