Monday, February 12, 2018

Groovy: Basic Concepts: Expressions

Expressions are constructs that are evaluated to yield a value.  Groovy supports expressions such as literals, constructions, functions and conditionals.

Literals

Number literals in Groovy can be defined as integer, decimal, octal, hexadecimal or binary.  These can be signed as either positive, implicitly, or negative, explicitly using the hyphen symbol.
int binaryLiteral = 0b110101
int octalLiteral = 07189
int base10Literal = 12229
int hexLiteral = 0x1AC4
float decimalLiteral = 1.234
In addition to simple numerical definition, Groovy inherits Java’s support for including underscores in a long number for readability (eg: int a = 123_456_789).  It also supports forcing numbers to a specific type by using suffixes:
Type Suffix
BigInteger G or g
Long L or l
Integer I or i
BigDecimal G or g
Double D or d
Float F or f
For String literals, Groovy defines the following forms: single quoted, double quoted, triple quoted, slashy and dollar slashy.
Single quoted strings are literals that are:
  • Denoted by a list of characters surrounded by a pair apostrophe (') characters
  • Implements string interpolation
  • Must be on a single line
String aString = 'a single quoted string'
Double quoted strings are literals that are:
  • Denoted by a list of characters surrounded by a pair of quotation (") characters
  • Implements string interpolation
  • Must be on a single line
String aString = "a double quoted string"
Triple quoted strings are literals that are:
  • Denoted by a list of characters surrounded by a pair of three apostrophe characters (''')
  • Does not implement string interpolation
  • Can span multiple lines
  • New lines can be removed by using the \ escape character a the end of the line
String aString = '''First line
A second line
A third line\
continued '''
Slashy strings are literals that are:
  • Defined by a list of characters surrounded by a pair of forward slash (/) characters
  • Implement string interpolation
  • Useful for managing regular expressions
  • Can span multiple lines
  • Empty strings cannot be represented as this type of literal
String aString = /.*foo.*/
Dollar slashy strings are literals that are:
  • Defined by a list of characters surrounded by $/ and /$
  • Can span multiple lines
  • Implements string interpolation
  • Uses a $ as an escape character
def dollarSlashy = $/
 Hello $name,
 today we're ${date}.
 
 $ dollar sign
 $$ escaped dollar sign
 \ backslash
 / forward slash
 $/ escaped forward slash
 $$$/ escaped opening dollar slashy
 $/$$ escaped closing dollar slashy
/$
String escape sequences:
Character Meaning
\t tabulation
\b backspace
\n newline
\r carriage return
\f Form feed
\\ backslash
\ single quote (for single quoted and triple single quoted strings)
\" double quote (for double quoted and triple double quoted strings)
\u#### a Unicode character

Constructions

Groovy allows for constructing composite values in code.  Examples include arrays and maps.
// Create an array in Groovy
def array = [1,2,3]
array << 4
It is possible to coerce Groovy into creating a literal, fixed-length array (ie: <type>[]) either by defining it as the specific data type or using the keyword as.
// Defined as a fixed size int primitive array
int[] intArray = [1,2,3]
// Defined internally as a fixed size long primitive
// array
def longArray = [1,2,3] as long[]
In addition to single-dimensional arrays, Groovy allows for creating multi-dimensional arrays.
def multiDim = [[1,2,3],[4,5,6]]
Defining a value in Groovy is accomplished in a similar method to Java, C or C++.
// Example variable definitions in Groovy
// datatype variablename (= optionalvalue)
def name = “A name”
int i = 0
long l = 123
Maps are created using the following notation:
// Define a map with three key-value pairs
def colors = [red:'FF0000', green:'00FF00', blue: '0000FF']

Function Calls

Groovy supports function calls, known as operations, as part of the base language.  These include:
Operators Precedence
Postfix expr++ expr--
Unary ++expr --expr +expr -expr ~ !
Multiplicative * / %
Additive + -
Shift << >> >>>
Relational < > <= >= instanceof

Conditional Expressions

Groovy supports the following conditionals:
Operator Precedence
Equality == !=
bitwise AND &
bitwise exclusive OR ^
bitwise inclusive OR |
logical AND &&
logical OR ||
Ternary ? :
Groovy also offers regular expressions as a form of conditional operator.  They come in two forms, the find and match operator.  The find operator returns a Java object which when evaluated as a conditional transparently calls the find() method.  The match operator simply returns a Boolean value.
// Example find
def text = "some text to match"
def m = text =~ /match/
assert m instanceof Matcher
if (!m) {
throw new RuntimeException("Oops, text not found!")
}
// Example match
m = text ==~ /match/
assert m instanceof Boolean
if (m) {
throw new RuntimeException("Should not reach that point!")
}

Iterative Expressions

Groovy supports a form of iterative expression in the form of the each and eachWithIndex methods.  For more details see the Loops section.

Constant and Variable Accesses

Constants and variables in Groovy are accessed by their defined name.  In both instances, accessing the variable will return its current value.  Constants in Java are defined as variables with the final modifier instructing the compiler that the value of the variable cannot change, emulating a constant.
For objects or maps, Groovy supports access the values via a ‘.’ notation where the variable is accessed in the form of ParentObject.variable.  Maps work in a similar manner where the form is Map.Key.
class Foo
{
 int val;
}

Foo f = new Foo()
// Dot notation for accessing members of an object
f.val = 7
 
// Define a map with three key-value pairs
def colors = [red:'FF0000', green:'00FF00', blue: '0000FF']
 
// Accessing the values can occur using the []
// notation or by the "." notation
assert colors['red'] == 'FF0000'
assert colors.green == '00FF00'
Groovy offers an additional variable access operator called the safe navigation operator.  This allows for accessing an object reference that may, or may not, have been defined.
def person = Person.find { it.id == 123 }
def name = person?.name
assert name == null

No comments: