Thanks for the info. I was trying to instantiate Lists like this: def ee = [] def rr = [1,2, "hello", ]
But I guess that's not going to happen. I know that if I used << or + on an immutable list, it would return an ArrayList. I was thinking that I could intercept those through metaprogramming on the java.util.Collections$UnmodifiableRandomAccessList class. I will look at those other libraries. But I just noticed that when people talk about Groovy supporting functional programming, immutable data seems to be ignored. People mostly talk about using closures on lists and maps. I was just wondering how far you could go using what Groovy provides out of the box. = Eric MacAdie On Mon, Jun 8, 2015 at 5:20 AM, Dinko Srkoč <dinko.sr...@gmail.com> wrote: > On 8 June 2015 at 06:32, Eric MacAdie <emaca...@gmail.com> 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 > > >