I am not sure I have the full history of when support started (at
least 15+ years ago) but dynamic Groovy unwraps a list as arguments:

def avg(int a, int b, int c) { (a + b + c)/3 }
assert avg(1, 2, 3) == 2    // normal invocation
def nums = [10, 20, 30]
assert avg(nums) == 20    // args are a list

It will only do this if the argument is a single List and no method
matching a single List argument was found. Relevant implementation:

https://github.com/apache/groovy/blob/master/src/main/java/groovy/lang/MetaClassImpl.java#L1242
https://github.com/apache/groovy/blob/master/src/main/java/groovy/lang/MetaClassImpl.java#L1246-L1253

You can turn this feature off with @TypeChecked/@CompileStatic.

Cheers, Paul.

<https://www.avast.com/sig-email?utm_medium=email&utm_source=link&utm_campaign=sig-email&utm_content=webmail>
Virus-free.www.avast.com
<https://www.avast.com/sig-email?utm_medium=email&utm_source=link&utm_campaign=sig-email&utm_content=webmail>
<#DAB4FAD8-2DD7-40BB-A1B8-4E2AA1F9FDF2>

On Sat, Mar 9, 2024 at 7:58 AM Simon Sadedin <ssade...@gmail.com> wrote:
>
> Hi,
>
> I am trying to understand some behaviour that is causing subtle and odd bugs 
> in our code.
>
> The behaviour is essentially that under very specific circumstances, Groovy 
> is coercing a List of Maps to a single Map. A condensed example is:
>
>    class Foo {
>         def foo(Map obj) {
>             println(obj)
>         }
>     }
>     z = [
>         [ a: 1, b:2]
>     ]
>     f = new Foo()
>     f.foo(z)
>
> In here, even though the foo() method requires a Map, the call does not throw 
> a type mismatch exception. Instead, the foo() method receives the Map object 
> that is the first entry of the list as its argument. Consequently, it prints:
>
> [a:1, b:2]
>
> If instead, it is passed a list containing two Maps, eg: z = [ [ a: 1, b:2], 
> [c:1, d:2] ], then it does throw a type conversion error. Also notable is 
> that it will always throw the type conversion error if you attempt to coerce 
> it outside the context of a function call, for example, using z.asType(Map).
>
> So it seems that under very specific circumstances that is both code context 
> and data dependent, Groovy will perform a different type of type conversion 
> to what it would do otherwise.
>
> Can anyone explain why it does this and what the rationale is?
>
> Cheers,
>
> Simon

Reply via email to