Search

Dark theme | Light theme
Showing posts with label Groovy 4. Show all posts
Showing posts with label Groovy 4. Show all posts

July 13, 2022

Groovy Goodness: Using Macros For Getting More Information About Variables

In a previous post we learned about the macros SV, SVI and SVD that return a string representation of variables with their name and value. Groovy 4 also added the NP and NPL macros that we can use to inspect variables. Instead of returning a GString instance these macros return a NamedValue instance or a list of NamedValue value instances. The NamedValue class is a simple class with a property name, containing the name of the variable, and property val with the value of the variable. The macro NP can be used when we have a single variable and result is a single NamedValue instance. An the macro NVL can be used with multiple variables. The result is a list of NamedValue instances where each instance represent a variable passed as argument to NVL.

In the following example we use NV and NVL:

def languages = ["Java", "Groovy", "Clojure"]

// Use NV macro to create a NamedValue object 
// with name and val properties containing the
// variable name and variable value.
def namedValue = NV(languages)

assert namedValue.name == "languages"
assert namedValue.val == ["Java", "Groovy", "Clojure"]
assert namedValue.class.name == "groovy.lang.NamedValue"


def alias = "mrhaki"
def name = "Hubert"
def age = 49

// We can pass multiple objects with the NVL macro
// and we get a List with multiple NamedValue objects.
def namedValues = NVL(alias, name, age)
assert namedValues.size() == 3
assert namedValues == [new NamedValue("alias", "mrhaki"), new NamedValue("name", "Hubert"), new NamedValue("age", 49)]

// We can use Groovy collection methods.
assert namedValues[0].name == "alias"
assert namedValues[0].val == "mrhaki"
assert namedValues.name == ["alias", "name", "age"]
assert namedValues.val == ["mrhaki", "Hubert", 49]
assert namedValues.find { nv -> nv.name == "age" }.val == 49

Written with Groovy 4.0.3.

Groovy Goodness: Using Macros For Getting String Representation Of Variables

Groovy 4 added some built-in macros that we can use in our code. A macro is code that will create new code. It does this by manipulating the Abstract Syntax Tree (AST) before the code is compiled. So when we use a macro, the macro will change the AST and those changes will be compiled. The three built-in macros SV, SVI and SVD can create a GString instance with the names and values of the variables that are passed as argument. This can be very useful to create some meaningful debugging statements. Normally we would have to type in the variable name ourselves followed by the value. Now with these macros we don't have to type the variable as the macro will add that to the AST for us.

The SV macro will use the toString method of the variable to get the value. When we want to use the inspect method for the value we can use the SVI macro. Finally we can use the SVD macro that uses the dump method to get the variable value.

In the following example we use all three macros with different variables:

def languages = ["Java", "Groovy", "Clojure"]

// With SV the toString method for the object is used.
// The name of the variable is also in our output.
assert SV(languages) == "languages=[Java, Groovy, Clojure]"
assert SV(languages).class.name == "org.codehaus.groovy.runtime.GStringImpl"

// With SVI the inspect method for the object is used.
assert SVI(languages) == "languages=['Java', 'Groovy', 'Clojure']"
assert SVI(languages).class.name == "org.codehaus.groovy.runtime.GStringImpl"

// We cannot assert here as the output contains the object instance representation
// and that changes with each run.
SVD(languages) // Possible output: languages=<java.util.ArrayList@8f636a77 elementData[Java, Groov, Clojure] size=3 modCount=3>
assert SVI(languages).class.name == "org.codehaus.groovy.runtime.GStringImpl"


// We can pass multiple objects to the SV, SVI and SVD macros.
def alias = "mrhaki"
def name = "Hubert"
def age = 49

assert SV(alias, name, age) == "alias=mrhaki, name=Hubert, age=49"
assert SVI(alias, name, age) == "alias='mrhaki', name='Hubert', age=49"
SVD(alias, name, age) // Possible output: alias=<java.lang.String@c077733c value=[109, 114, 104, 97, 107, 105] coder=0 hash=-1065913540 hashIsZero=false>, name=<java.lang.String@817bc072 value=[72, 117, 98, 101, 114, 116] coder=0 hash=-2122596238 hashIsZero=false>, age=<java.lang.Integer@31 value=49>    

Written with Groovy 4.0.3.