A friend of mine was banging his head against the wall because this Groovy code.
Let’s explain very quickly what this does.
First, we create an empty map and then we define a key that is the result of a string interpolation. The key will be "job-4"
.
Then we verify if the key is already on the map. If the map does not have the key, we add it with the value 1
, and then we do the same again, but just this time the key will be on the map and nothing will change. The value for key "job-4"
, should remain the same, that is value 1
.
Let me tell you something, we are all wrong. The line println(cache[key])
will in fact, print 2
.
This is madness!!! so we looked at other languages to see if one of them behaves in the same way Groovy does.
In Ruby we do:
it prints out the value 1
as expected!
In JavaScript we do:
it prints out the value 1
as expected!
In Elixir we do:
it prints out the value 1
as expected!
In Scala we do:
it prints out the value 1
as expected!
What is wrong with Groovy!!!!???
The problem comes from the way Groovy manages dynamic typing and string interpolation.
When Groovy does the string interpolation, the resulting type is GStringImpl
which means the comparison is not in the way you expected. We need to force GStringImpl
to be a String
be doing .toString()
.
If we only do:
def key = "job-${4}".toString()
everything starts working as expected.
Stop using Groovy!!!