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 14:52:03 GMT
On 8 June 2015 at 16:02, Eric MacAdie <emacadie@gmail.com> wrote:
> 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.

Not that easily anyway.

>
> 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.

It depends on how much of a fundamentalist you want to be. Closures on
data structures enable one to program in a functional style. As a nice
bonus, one can use composition, currying (actually partial
application), trampolining, or memoization on Closures themselves, and
a couple of  AST transformations such as @Immutable or @TailRecursive.

As for functional data structures you should probably look elsewhere.
Some other things might be a bit surprising as well, like `final`
local variables (try it).

Cheers,
Dinko

>
> = 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