On 8 June 2015 at 06:32, Eric MacAdie <[email protected]> wrote:
>
> Has anyone ever tried to intercept the constructors for ArrayList?
>
> I would like to intercept them, and call asImmutable() on them, to be a bit
> more functional. And just general curiosity.
>
> According to the shell, there are three constructors for ArrayList:
>
> groovy:000> ArrayList.class.getConstructors()
> ===> [public java.util.ArrayList(java.util.Collection), public
> java.util.ArrayList(), public java.util.ArrayList(int)]
>
> [...]
> But I cannot figure out how to intercept the
> java.util.ArrayList(java.util.Collection). Here are a couple of attempts:
>
> java.util.ArrayList.metaClass.constructor = { java.util.Collection arg ->
> println "Intercepting Collection call, here is arg: ${arg.class.name}"
> constructor = ArrayList.class.getConstructor( java.util.Collection )
> println "just made constructor: ${constructor}"
> constructor.newInstance( arg ).asImmutable()
> }
> [...]
That code actually works. Example:
ArrayList.metaClass.constructor = { Collection arg ->
def ctor = ArrayList.getConstructor(Collection)
ctor.newInstance(arg).asImmutable()
}
def xs = new ArrayList([1, 2, 3])
assert xs == [1, 2, 3]
assert xs[0] == 1
xs[0] = 42 // throws UnsupportedOperationException
Also, the easiest way to make an empty immutable list is to use
`Collections.emptyList()` (your example with parameterless
constructor):
def nil = Collections.emptyList()
assert nil == []
nil << 42 // throws UnsupportedOperationException
All that said, changing ArrayList constructors to make immutable lists
may not be the best approach to go all functional for a couple of
reasons. Some of them might be:
* you can't use list literals (`[1, 2, 3]` is still not immutable)
* working with lists will pretty soon get you back to plain mutable ones:
def immut1 = new ArrayList([1, 2])
def immut2 = new ArrayList([3, 4])
def mut = immut1 + immut2
mut[0] = 42
assert mut == [42, 2, 3, 4]
* having immutable but not persistent data structures may be expensive
because you have to do a lot of defensive copying.
If you really wanted immutable structures in the functional sense, it
might be best to use an existing library, perhaps clj-ds[1] (Clojure's
data structures without Clojure), or FunctionalGroovy[2] - a port of
FunctionalJava[3] to Groovy.
Cheers,
Dinko
[1]: https://github.com/krukow/clj-ds
[2]: https://github.com/mperry/functionalgroovy
[3]: http://www.functionaljava.org/
> = Eric MacAdie
>