2. Agenda– Tour de Force
•
•
•
The Language
Use Cases
Everything is an Object
•
•
•
Collections: Ranges, Lists and Maps
Control Structures
Operator Overloading
•
Closures: Higher-Order Functions
•
Categories: Extending Classes at Runtime
•
Examples
3. Groovy
•
Is a
– Scripting Language
– Regular Programming Language
•
Is derived from Java
•
Is a dynamic language
•
Is officially defined in the Java Community Process
– JSR-241 (Java Specification Request)
•
Is executed on a standard Java Virtual Machine
•
•
•
Exists since 2003 (It is de facto an old language)
Is in the Top 20 list of TIOBE
Current version is 2.1.8
4. An Example (Java)
public class HelloWorld {
public static void main(String [ ] args) {
System.out.println(„HelloWorld“);
}
}
•
The Simplest existing Java Program
5. An Example (Groovy)
println „Hello World“
Hello World
Comment: The example on the previous page is correct Groovy code also
6. Use Cases
•
Programming of Scripts instead of
– Sh, Perl, Python, Ruby …
•
Unit-Tests
– Much simpler way of writing test cases
– Direct support for stub and mock objects
•
Full-blown Applications
– Frameworks
• Grails as a Web-Application Framework
• Griffon as a Swing-Application Framework
•
Integration in large Applications
– As Glue Code
– Class-by-Class Substitution for Java e.g. in Spring
– As Configuration Language
– As Domain-Specific Language
7. Language Features
• Very similar to Java
– Easy to learn
– In fact, every Java Program is a valid Groovy program
– Java Object Model is used
• Groovy tries to follow the principle of least surprise
• All Java classes and frameworks can be used
– High number of existing frameworks
• Translated Groovy classes can be used by Java
– Integration in both directions
• Typing
– Strong or weak
– Dynamic or static
8. Everything is an Object
•
Java differentiates primitive data types and objects
– Original motivation were performance problems
– Leads to impedance mismatch
•
•
translate “problems”
In Groovy everything is an Object
– Numbers are objects as well
5.times { println „Hallo Welt“ }
Hallo Welt
Hallo Welt
Hallo Welt
Hallo Welt
Hallo Welt
9. Explicit Typing is optional
•
Duck Typing
– Known from Scripting languages
•
Simplifies Programming
•
We do not need to provide the type of a variable
•
Under the hood Groovy uses explicit Typing
def a = 1
a is of Type Integer (simplified)
10. Collections
•
Groovy adds a new Collection Type
– Range
•
And adds a lot of syntactic sugar for existing Collection Types
– Lists
– Maps
•
Furthermore, the interfaces are harmonized
– Example
Method size()
11. Collections: Range (a special variant of List)
• Define a number of elements (a range) in an interval
1..5
Inclusive: Range 1 - 5
• Ranges are Objects
def r = 1..<5
Exclusive: Range 1 - 4
• We can iterate through all elements
r.each { n -> println n }
1
2
3
4
• Elements are only created on demand
• Classes implementing the Interface Comparable and providing the methods next()
und previous(), can be used in Ranges.
12. Collections: Lists
•
Simplified Notation (extends the Java-Type List)
def list = [1, 2]
•
Adding and Removing Values
list += 3
list = list - [2]
•
We can iterate over the elements
list.each { n -> println n }
•
[1, 2, 3]
[1, 3]
1
3
Subscript operator is supported (as with Ranges)
14. Control Structures
•
New For Loop Syntax
for ( i in 1..5 )
println „Hello $i“
Hello 1
Hello 2
Hello 3
Hello 4
Hello 5
•
Every normal Java control structure is supported (including For Loops)
•
Boolean decision much more general through the use of
Groovy Truth
Coercion of Collections, Iterators, Enumerations, Maps, Matchers, Strings,
Numbers and Object References to a boolean expression
15. Control Structures: Switch Statement
•
Switch much more general than Java
(Example with Type, Range and Closure)
switch ( val ) {
case { it > 3 }: println „$val is larger than 3“; break
case 5..9:
println „$val is in the Range 5 – 9“; break
case Number: println „$val is of Type Number “; break
}
16. Operator-Overloading(1)
•
Impossible in Java
•
Widely used in Groovy
•
Provided for many existing Java classes
•
Works by implementing the respective Method
Example
Operator +
Operator …
•
Method plus()
Method minus()
Thus your own implementations are straightforward
17. Operator Overloading(2)
class Complex {
BigDecimal r
BigDecimal i
def plus (Complex c) {
new Complex (r : this.r + c.r, i : this.i + c.i)
}
}
def res = new Complex(r:1, i:-1) + new Complex (r:1, i:1)
println "$res.r + $res.i i"
2+0i
18. Closures: Higher-Order Functions
•
Basic Idea: Methods are Objects
– Known from functional programming
– There we have first-order (and higher-order) functions
•
Anonymous inner classes on Steroids
•
Usage
– Separation of Concerns
• Separation of Iteration and Logic
• Central Resource Handling
– Functional Programming Approaches
19. Closures: Definition (1)
•
We have met (anonymous) Closures already
map.each { entry -> println „$entry.key: $entry.value“}
case { it > 3 }:
•
println „$val is larger than 3“
General Definition
def c = { p1, p2, p3 = 0 ->
[ Source of the Closure]
}
Parameters can accept Default Values
If no Parameter is given, then
Implicit Parameter it
Return Value is the Result of the
last statement
20. Closures: Example
def square = { x -> x * x }
4
println square(2)
r = 1..5
r.each { println square(it) }
1
4
9
16
25
def cubed = { x -> x * square (x) }
r.each { println cubed(it) }
Implicit Parameter it
1
8
27
64
125
21. Closures: Functional Programming (1)
•
Definition
„In mathematics and computer science, currying is the technique of transforming a
function that takes multiple arguments (or a tuple of arguments) in such a way that
it can be called as a chain of functions, each with a single argument (partial
application). It was originated by Moses Schönfinkel and later re-discovered by
Haskell Curry. Because of this, some say it would be more correct to name it
schönfinkeling. “
– Wikipedia
•
Fixes the number of arguments to a function, thereby generating a new function
•
Allows the concatenation of functions
22. Closures: Functional Programming (2)
def mul = { x, y -> x * y }
def mul2 = mul.curry(2)
def mul5 = mul.curry(5)
println mul2(3)
println mul5(2)
Equals { y -> 2 * y }
Equals { y -> 5 * y }
6
10
def komp = { g, f, x -> g( f(x) ) }
def mul10 = komp.curry(mul2, mul5)
println mul10(5)
// Left Shift Operator
mul10 = mul2 << mul5
println mul10(5)
g°f (x) := g(f(x))
Currying with Closures
50
23. Extending existing Classes using Categories
•
•
•
Third-party Classes sometimes need to be extended or changed
Categories change behaviour of Objects and Classe at Runtime
Adding or Changing Methods
class HelloCategory {
public static String hello(String i) { return "Hello, $i" }
}
def testString = "Joachim"
use(HelloCategory) {
println testString.hello()
}
Hello, Joachim
25. Example XML-Parsing: An XML-Structure
<groovy>
<music>
<tune>
<title>The 59th Street Bridge Song</title>
<artist>Simon and Garfunkel</artist>
</tune>
<tune>
<title>Monday Monday</title>
<artist>The Mamas and The Papas</artist>
</tune>
<tune>
<title>Goodnight Moon</title>
<artist>Shivaree</artist>
</tune>
<tune>
<title>Suddenly</title>
<artist>Soraya</artist>
</tune>
</music>
</groovy>
26. XML-Parsing: The Groovy Script and the Output
Reference to XML-Tree
(equivalent to the root element groovy)
The Script
result = new XmlSlurper().parse(new File(args[0]))
result.music.tune.each {
elem -> println "$elem.title, $elem.artist"
}
The Output
The 59th Street Bridge Song, Simon and Garfunkel
Monday Monday, The Mamas and The Papas
Goodnight Moon, Shivaree
Suddenly, Soraya
GPath
Expression
27. Example: WebServer (25 Lines)
def webPath = args[0]
def getPattern = /GET (/?[^? ]*)??([^ ]+)?s+HTTP/[.d]+/
def server = new ServerSocket(5926)
while(true) {
server.accept() { socket ->
socket.withStreams { input, output ->
def line, resource
def reader = input.newReader()
while(line = reader.readLine()) {
println line
def match = line =~ getPattern
if(match)
resource = match[0][1]
}
def f = new File ("$webPath/$resource")
if(f.directory)
f = "$webPath/$resource/index.html" as File
if(!f.exists())
f = "$webPath/error.html" as File
}
output << "HTTP/1.0 200 OKn" //{{9}}
output << "Content-Type: text/htmlnn"
output << f.asWritable()
} }
29. Example Domain Specific Language
•
(Simplified) Language focusing on a specific problem area
•
Used by Domain Experts, not necessarily IT-Personnel
•
Focuses on the Problem Domain
•
Allows a natural and succinct expression of problems in the problem domain
•
Two Approaches
– Internal DSL
– External DSL
•
Simple examples for a DSL
3.€ + 4.$ + 10.Yen
2.km + 5.mm + 3.yd+ 2.mi
30. DistanceDSL: The Class Unit
class Unit {
def ratio
String name
public static final mm = new Unit(ratio : 0, name : "millimeter")
public static final cm = new Unit(ratio : 1, name : "centimeter")
// equivalent Entries for m, km, yd, mi
…
static def convertUnit(Distance d, Unit newUnit) {
def factor = ratioTable[d.unit.ratio][newUnit.ratio]
if(factor)
return d.length * factor
else
return d.length / ratioTable[newUnit.ratio][d.unit.ratio]
}
static ratioTable = [
//
mm,
cm,
m,
km, y, mi
[
1,
0,
0,
0,
0, 0 ],
[
10,
1,
0,
0,
0, 0 ],
// äquivalente Einträge für m, km, yd, mi
…
]
}
// mm
// cm
31. DistanceDSL: The Class Distance
class Distance implements Comparable {
BigDecimal length
Unit unit
Distance plus(Distance operand) {
def newLength = this.length + Unit.convertUnit(operand, this.unit)
new Distance(length : newLength, unit : this.unit)
}
Distance minus(Distance operand) {
def newLength = this.length - Unit.convertUnit(operand, this.unit)
new Distance(length : newLength, unit : this.unit)
}
int compareTo(other) {
if(this.unit == other.unit)
return this.length <=> other.length
return this.length <=> Unit.convertUnit(other, this.unit)
}
String toString() {
"$length $unit.name"
}
}
32. DistanceDSL: The Category
class DistanceCategory {
static Distance getMm(Number n) {
new Distance(length : n, unit : Unit.mm)
}
static Distance getMm(Distance d) {
new Distance(length : Unit.convertUnit(d, Unit.mm), unit : Unit.mm)
}
…
Equivalent Lines for getCm(), getM(), getKm(), getYd(), getMi()
}
34. Meta Object Protocol (1)
•
Normally an Object has a fixed set of methods and properties (or interface)
•
What happens if the Object can decide each time how to interpret a method call or
property access?
•
Allows sensible reaction to calls that are not known at implementation time
35. Meta Object Protocol (2): A Simple Example
• React to a call to a method that is not implemented
wird aufgerufen für alle nicht
implementierten Methoden
class MOPBeispiel {
public invokeMethod(String method, Object params) {
println "I have been called with $method()"
}
}
bsp = new MOPBeispiel()
bsp.helloWorld()
I have been called with helloWorld
36. Groovy: Is it worth it?
Interlude: The mythical Man-Month
Book written in the 70‘s, Author Frederick P. Brooks, Jr.
Contains basic wisdom of project management that is still not followed
In this context interesting
•
Use of Higher Abstractions leads to a Growth in Productivity by a Factor, not by
a percentage (p. 186)
– Classical Example is Assembler vs. C
•
Introduction of new Languages: In the Beginning High Cost, Wins are reaped
later (p. 221
•
Learning the Vocabulary – i.e., the frameworks and libraries – is timeconsuming (p. 224)
– Example Java vs. C#
37. Groovy: Is it worth it?
• Language provides Higher Abstractions than Java
• Pro: Groovy is fully compatible to Java
– Java Developers can use Groovy at once
– Every Library and Framework is directly available
• Con: Runtime Performance is lower. But
– Call Site Caching allows Speed-Ups
– Java 1.7 provides new VM-Byte-Code that allows this extremely fast
– Difference is small (typically 1.5)
– Groovy provides static compilation that leads to faster code
– Critical parts of the Application can be written in Java
• Groovy is the dynamic language with the lowest cost for introduction and usage