'Optional chaining operator in groovy not working as expected?
How can I concisely set a default value for a value of a closure that is not populated?
Below I thought using the optional chaining operator would prevent throwing an exception, but I still got an exception.
myfunction {
FOO="myfoo"
BAZ="mybaz"
}
def myfunction(Closure body = {}) {
body()
foo = body?.FOO ?: "defaultFoo"
// getting exception since BAR isnt defined
bar = body?.BAR ?: "defaultBar"
println("foo=" + foo + " bar=" + bar)
}
Solution 1:[1]
You can solve it by setting a dedicated Binding on your closure with a map that returns a default value (e.g. null) for non-existing keys.
myfunction {
FOO="myfoo"
BAZ="mybaz"
}
def myfunction(Closure body = {}) {
def binding = new Binding([:].withDefault {}) // <1>
body.setBinding(binding) // <2>
body()
foo = binding.FOO // <3>
bar = binding.BAR
println("foo=" + foo + " bar=" + bar)
}
Output:
foo=myfoo bar=null
There are three critical changes to your code.
- You define
new Binding([:].withDefault {})object, where[:].withDefault {}is a map that returns a value defined inside the closure for any key that does not exist. In our case, we use an empty closure to returnnullvalue, but if we do e.g.[:].withDefault { 1 }, then we create a map that returns1for non-existing keys. - Next, you have to call
body.setBinding(binding)to make use of this customBindinginstance. - And finally, you read values from the
bindingobject, not thebodyclosure.
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|---|
| Solution 1 | Szymon Stepniak |
