groovy-users mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From Eric MacAdie <emaca...@gmail.com>
Subject Re: Intercepting Constructors for ArrayList
Date Mon, 08 Jun 2015 14:02:18 GMT
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.srkoc@gmail.com> wrote:

> On 8 June 2015 at 06:32, Eric MacAdie <emacadie@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
> >
>

Mime
View raw message