groovy-users mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From Dinko Srko─Ź <dinko.sr...@gmail.com>
Subject Re: Intercepting Constructors for ArrayList
Date Mon, 08 Jun 2015 10:20:50 GMT
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