ES6 object property shorthand with Groovy
Recently someone asked on StackOverflow whether there is an equivalent in Groovy for the JavaScript shorthand for properties of the object literal. It basically looks like this:
const a = 'foo'; const b = 42; const c = {}; const obj = { a, b, c }; // the same as: const obj = { a: a, b: b, c: c };
While this feature is not supported in Groovy directly, it's easy to reproduce using a very underused feature: a macro. Macros are supported in Groovy since 2.5.
Create new file to contain all macros. E.g. Macros.groovy
:
import org.codehaus.groovy.ast.tools.GeneralUtils import org.codehaus.groovy.macro.runtime.* import org.codehaus.groovy.ast.expr.* import org.codehaus.groovy.syntax.* class Macros { @Macro static Expression mapOf(MacroContext ctx, final Expression... exps) { return new MapExpression( exps.collect{ new MapEntryExpression(GeneralUtils.constX(it.getText()), it) } ) } }
Then compile this file (this is important to do first, or else Groovy gets confused when something references the class, but it's not there):
# groovyc Macros.groovy
Next make the macro known. There must a file
META-INF/groovy/org.codehaus.groovy.runtime.ExtensionModule
in the
classpath containing the following lines to make Macros
from above
work:
moduleName=Some name moduleVersion=0.1-SNAPSHOT extensionClasses=Macros
And then finally try it out:
def labels=["a", "b"] def values=[1, 2] println( [labels, values] .transpose() .collect{ label, value -> mapOf(label,value) } )
And run it:
# groovy test.groovy [[label:a, value:1], [label:b, value:2]]