(This question is quite subjective for Stack O.)
My answer uses metaclass functionality (and other minor functions). The solution is not short in implementation, but is short in use (and idiomatic, in the sense of writing a structure):
a=['oxford','cambridge'] println a.toString() *prints* >> 'oxford' and 'cambridge'
Decision:
// quote def q = {"'$it'"} // apply Oxford for N > 2 def f = {it[0..-2].join(", ") + ", and " + it[-1]} // map list size to Oxford function (N > 2 is default) def fmap = [:].withDefault{f} fmap[0] = {""} fmap[1] = {"${it[0]}"} fmap[2] = {"${it[0]} and ${it[1]}"} // re-define toString() to call Oxford function from map // (with quoted items) ArrayList.metaClass.toString = { -> fmap[ delegate.size() ].call( delegate.collect{q(it)} ) }
Usage example:
a=[] ; println a.toString() a=['oxford'] ; println a.toString() a=['oxford','cambridge'] ; println a.toString() a=['oxford','cambridge','comma','space'] ; println a.toString()
Output from examples (_ denotes an empty string):
_ 'oxford' 'oxford' and 'cambridge' 'oxford', 'cambridge', 'comma', and 'space'
Michael easter
source share