Thirty years ago the famous computer scientist Tony Hoare said “I have regarded it as the highest goal of programming language design to enable good ideas to be elegantly expressed”. His comment sums up what has been driving the evolution of programming languages: the desire to create increasingly expressive languages. In this talk you will learn about two modern JVM languages that strive to be expressive in very different ways. We will talk about Groovy, which is a dynamically-typed language, and Scala, which is a statically-typed language. You will learn about the key features of each language as well as their benefits and the drawbacks.
Factors to Consider When Choosing Accounts Payable Services Providers.pptx
In pursuit of expressivity: Groovy and Scala compared
1. In pursuit of expressivity:
Groovy and Scala compared
Chris Richardson
Author of POJOs in Action
Founder of CloudFoundry.com
chris@chrisrichardson.net
@crichardson
2. Overall presentation goal
Examine the good,
the bad and the ugly
aspects of
developing with
Groovy and Scala
4/3/11 Copyright (c) 2011 Chris Richardson. All rights reserved.
Slide 2
3. About Chris
• Grew up in England and live in Oakland, CA
• Over 25+ years of software development
experience including 14 years of Java
• Speaker at JavaOne, SpringOne, NFJS,
JavaPolis, Spring Experience, etc.
• Organize the Oakland JUG (
http://bit.ly/ebjava) and the Groovy Grails
meetup (http://bit.ly/oakgrails)
http://www.theregister.co.uk/2009/08/19/springsource_cloud_foundry/
4/3/11 Copyright (c) 2011 Chris Richardson. All rights reserved.
Slide 3
4. Agenda
o Evolution of programming
languages
o Favorite Groovy features
o The frustration of using Groovy
o Scala: expressiveness and compile-
time checking
o The trouble with Scala
4/3/11 Copyright (c) 2011 Chris Richardson. All rights reserved.
Slide 4
5. Lots of programming languages
This site lists 8512 languages, complete with 17837 bibliographic records
featuring 11064 extracts from those references. It is in effect a family
tree of languages with 5445 links, making it not only the biggest
programming language family tree around, but also one of the largest
idea-genealogical projects undertaken.
http://hopl.murdoch.edu.au/
4/3/11 Copyright (c) 2011 Chris Richardson. All rights reserved.
Slide 5
6. The Elite v. The Masses
The Elite Mainstream
o Lisp o Thought Lisp and
n Invented in the 1960s Smalltalk were:
n Dynamic functional n Weird (Too different
language from Algol)
n Dynamic object-oriented n Too resource hungry
language (mid-1980s) (probably were for the
o Smalltalk time)
n Invented in the 1970s o So the mainstream used:
n Dynamic object-oriented
Pascal, C, C++, ….
language o Not so safe, manual
o Safe, garbage collection, memory management,
rich, … primitive, …
4/3/11 Copyright (c) 2011 Chris Richardson. All rights reserved.
Slide 6
7. LISP/CLOS – an early (late 1980s)
dynamic language
(defclass Account ()
((account-id :accessor account-id :initarg :account-id)
(balance :accessor account-balance :initarg :balance)) Develop by adding and
) changing program
elements in a running VM
(defmethod debit ((Account account) amount)
(decf (account-balance account) amount))
(defmethod credit ((Account account) amount)
(incf (account-balance account) amount))
CL-USER 5 > (setq a (make-instance 'account :account-id "abc123" :balance 10.0))
#<ACCOUNT 200C05AF>
CL-USER 6 > (describe a)
#<ACCOUNT 200C05AF> is an ACCOUNT
ACCOUNT-ID "abc123"
BALANCE 10.0
CL-USER 7 > (debit a 5)
5.0
CL-USER 8 > (describe a)
#<ACCOUNT 200C05AF> is an ACCOUNT
ACCOUNT-ID "abc123"
BALANCE 5.0
4/3/11 Copyright (c) 2011 Chris Richardson. All rights reserved.
7
8. … a very dynamic language
(defclass Account ()
((account-id :accessor account-id :initarg :account-id) Existing instances
(balance :accessor account-balance :initarg :balance) are updated when
(description :accessor account-description :initarg :description)) the class is redefined
)
CL-USER 9 > (describe a)
#<ACCOUNT 2168DCBF> is an ACCOUNT
ACCOUNT-ID "abc123"
BALANCE 10.0
DESCRIPTION #<unbound slot>
CL-USER 10 > (setf (account-description a) "checking account")
"checking account"
CL-USER 11 > (describe a)
#<ACCOUNT 2168DCBF> is an ACCOUNT
ACCOUNT-ID "abc123"
BALANCE 10.0
DESCRIPTION "checking account"
4/3/11 Copyright (c) 2011 Chris Richardson. All rights reserved.
8
9. Along came Java
o Provided the masses with:
n Garbage collection
n Safety, reliability and security
o And 10+ years passed…
4/3/11 Copyright (c) 2011 Chris Richardson. All rights reserved.
Slide 9
10. Ruby on Rails woke up the Java
community
o Ruby on Rails:
n Significantly more productive
n Simplicity of Convention over
Configuration
o Motivated the Java community to
improve: frameworks such as Spring
improved considerably
o And…
4/3/11 Copyright (c) 2011 Chris Richardson. All rights reserved.
Slide 10
11. …Highlighted Problems with Java
o Tedious collection processing
o Painful object construction code
n No literals for collections
n Need to use Builders for creating hierarchies
o Tedious XML processing
o Types:
n Verbose declarations
n Generics are complicated
o Fixed set of control constructs
o Limited support for DSLs
=>
o Reopened the debate about programming
languages
o Dynamic languages became interesting again
4/3/11 Copyright (c) 2011 Chris Richardson. All rights reserved.
Slide 11
12. Dynamic languages on the JVM
o JRuby
n http://jruby.codehaus.org
n Ruby on the JVM
o Jython
n http://www.jython.org/Project
n Python on the JVM
o Clojure
n http://clojure.org/
n Functional programming language
n Software Transactional Memory
n …
o Groovy
n http://groovy.codehaus.org/
n Java-compatible, dynamic language
4/3/11 Copyright (c) 2011 Chris Richardson. All rights reserved.
Slide 12
13. Small but growing
4/3/11 Copyright (c) 2011 Chris Richardson. All rights reserved.
Slide 13
14. Static languages on the JVM
o (Java)
o Fortress
o Gosu
o Scala
o …
http://www.is-research.de/info/vmlanguages/?s=static
4/3/11 Copyright (c) 2011 Chris Richardson. All rights reserved.
Slide 14
15. Scala and Gosu adoption – Smaller
but growing
4/3/11 Copyright (c) 2011 Chris Richardson. All rights reserved.
Slide 15
16. Agenda
o Evolution of programming languages
o Favorite Groovy features
o The frustration of using Groovy
o Scala: expressiveness and compile-
time checking
o The trouble with Scala
4/3/11 Copyright (c) 2011 Chris Richardson. All rights reserved.
Slide 16
17. About Groovy
o Object-oriented, dynamic language
o Made popular by the Grails
framework:
n Rails-like productivity
n Using robust Java frameworks including
Spring and Hibernate
4/3/11 Copyright (c) 2011 Chris Richardson. All rights reserved.
Slide 17
18. The good news
o Easy to learn
n Designed to be Java compatible
n Interactive Shell
o Great support for DSLs
o Closures:
n Easy collection processing
n New control constructs
o Property/method missing mechanism
o Good XML handling
o Meta-classes for dynamically defining
new program elements => foundation
for Grails
4/3/11 Copyright (c) 2011 Chris Richardson. All rights reserved.
Slide 18
19. Intentionally compatible with Java
o Groovy objects are Java objects
o Groovy collections are Java collections
o Groovy can call Java
n e.g. leverage all those Java libraries
o Java can call Groovy, e.g. Groovy
objects can be:
n Spring beans
n Hibernate objects
o Easy to write a module of a project
Groovy => Easy to incrementally adopt
4/3/11 Copyright (c) 2011 Chris Richardson. All rights reserved.
Slide 19
20. Groovy can look like Java
import javax.crypto.Mac;
import javax.crypto.spec.SecretKeySpec;
class EC2RequestExecutor { Java-like syntax
Log logger = LogFactory.getLog(getClass())
public String calculateRFC2104HMAC(String data, String key) {
try {
SecretKeySpec signingKey = new SecretKeySpec(key.getBytes("UTF8"),
HMAC_SHA1_ALGORITHM)
Mac mac = Mac.getInstance(HMAC_SHA1_ALGORITHM)
mac.init(signingKey)
byte[] rawHmac = mac.doFinal(data.getBytes())
return new String(Base64.encodeBase64(rawHmac))
}
catch (Exception e) {
throw new RuntimeException("Failed to generate HMAC : ", e)
}
}
4/3/11 Copyright (c) 2011 Chris Richardson. All rights reserved.
Slide 20
21. Groovy is concise and expressive
def configureAsMaster() {
writeFile fileName: "/etc/my.cnf", templateName: "/templates/master.my.cnf"
restartService "mysqld"
exec command: "mysql -u root",
templateName: "/templates/createSchema.sql", No parens
templateArgs: [schemaSpec: schemaSpec] Keyword parameters
executeSchemaScripts()
}
class TomcatServer { tomcatServer.contexts
No get…()
def getContexts() {
webApps.context
}
}
4/3/11 Copyright (c) 2011 Chris Richardson. All rights reserved.
Slide 21
22. An interactive shell
Great for experimentation and learning
4/3/11 Copyright (c) 2011 Chris Richardson. All rights reserved.
Slide 22
23. Literals for lists and maps
def myList = ["a", "b", "c"]
def params = ['Action': 'RunInstances',
'MinCount': n.toString(), 'MaxCount': n.toString(),
' ImageId': awsProperties."imageId.${instanceType}",
'KeyName': awsProperties.keyName,
' InstanceType': instanceType] + extraParams
def response = requestor.executeRequest(params)
4/3/11 Copyright (c) 2011 Chris Richardson. All rights reserved.
Slide 23
24. GStrings
o Templating mechanism
o Embedded Groovy expressions
o Multi-line strings
def schemaScript = """
DROP SCHEMA IF EXISTS ${schemaSpec.name};
CREATE SCHEMA ${schemaSpec.name};
"""
4/3/11 Copyright (c) 2011 Chris Richardson. All rights reserved.
Slide 24
25. Closures – collection processing
public EC2Server findInstance(String instanceId) {
def server = servers.find {instanceId == it.instanceId}
if (server)
return server
else throw new RuntimeException(….)
}
assertEquals(["aa", "bb", "cc"],
["a", "b", "c"].collect { elem -> elem + elem }
Simplified collection processing
No ugly anonymous inner classes
4/3/11 Copyright (c) 2011 Chris Richardson. All rights reserved.
Slide 25
26. Closures – new control structures
public class Ssh {
def withTunnel(String publicDnsName, int localPort, int remotePort, Closure closure) {
SshConnection sshConnection = makeSshConnection(publicDnsName);
try {
sshConnection.connect()
…
return closure.call()
} finally {
sshConnection.close()
}
}
}
class EC2 {
String snapshotEbsVolume(String hostName, EbsVolume ebsVolume, String schemaName) {
int localPort = PortUtil.allocatePort()
def result = ssh.withTunnel(hostName, localPort, 3306) {
…
}
return (String)result
}
}
4/3/11 Copyright (c) 2011 Chris Richardson. All rights reserved.
Slide 26
27. Closures details
groovy:000> x = { println z }
===> groovysh_evaluate
$_run_closure1@658ba380
groovy:000> x.delegate = [z: 99]
===> Foo@564a5320
groovy:000> x.call()
Used to resolve
99 unbound methods and
properties
===> null
For example, Builders
set the delegate
4/3/11 Copyright (c) 2011 Chris Richardson. All rights reserved.
Slide 27
28. Simple reusable code
interface Quackable {
void quack();
Java:
} complexity of
class QuackableContainer<T extends Quackable>
generics
void add(T element) {
element.quack();
…
}
…
}
class QuackableContainer { Groovy: just assume that
void add(element) { there is a quack() method
element.quack()
…
}
4/3/11 Copyright (c) 2011 Chris Richardson. All rights reserved.
Slide 28
29. Method Missing
public class ClassWithMissingMethods {
def methodMissing(String name, args) {
Closure method = makeMethodImplementation(name)
if (method) {
method(args)
} else {
throw new MissingMethodException(name, getClass(), args)
}
}
def makeMethodImplementation(String name) {
….
}
}
def foo = new ClassWithMissingMethods()
foo.nonExistentMethod()
4/3/11 Copyright (c) 2011 Chris Richardson. All rights reserved.
Slide 29
30. Groovy metaclasses
public class StringMetaclassExampleTest extends GroovyTestCase {
void testAddMethodToString() {
String.metaClass.doubleString = { -> delegate + delegate }
String.metaClass.static.makePowerString = { String s, int n ->
def result = s
n.times { result = result.doubleString() }
result
}
assertEquals "JavaZoneJavaZone", "JavaZone".doubleString()
assertEquals "OsloOsloOsloOslo", String.makePowerString("Oslo", 2)
}
}
Runtime definition of program elements
The foundation of many powerful features
4/3/11 Copyright (c) 2011 Chris Richardson. All rights reserved.
Slide 30
31. XML and GPath expressions
<RunInstancesResponse>
…
<instancesSet>
<item>
<instanceId>i-4ef21327</instanceId>
<imageId>ami-3795705e</imageId>
<instanceState>
<code>0</code>
def client = new HttpClient() <name>pending</name>
… </instanceState>
def responseStream = <dnsName/>
…
getMethod.getResponseBodyAsStream()
</RunInstancesResponse>
def parser = new XmlParser(false, false)
def response = parser.parseText(responseStream)
def newServers = response.instancesSet.item.collect {
new EC2Server(this, awsProperties, ssh,
it.instanceId.text(),
it.instanceState.name.text())
}
4/3/11 Copyright (c) 2011 Chris Richardson. All rights reserved.
Slide 31
32. Metaclasses enhance JDK classes
groovy:000> new File("/Users/cer/.bashrc").text
===> export PATH=/Users/cer/tools/apache-maven-3.0/bin:
$PATH
groovy:000> l = [1,2,3]
===> [1, 2, 3]
groovy:000> l.getClass()
===> class java.util.ArrayList
groovy:000> l.getClass().metaClass.foo = { delegate.size }
===> groovysh_evaluate$_run_closure1@13a66c87
groovy:000> l.foo()
===> 3
4/3/11 Copyright (c) 2011 Chris Richardson. All rights reserved.
Slide 32
34. Grails plugins use metaclasses
o Key part of the Grails plugins
o Plugins can dynamically add methods,
e.g. GORM persistence methods
o Injected methods are closures that
have access to the Spring application
context
n Less need for traditional dependency
injection
n Alternative to AOP static crosscutting or
(non-POJO) inheritance
4/3/11 Copyright (c) 2011 Chris Richardson. All rights reserved.
Slide 34
35. Grails/GORM persistence methods
class Customer { Implemented using
String name metaclasses and method
} missing
Customer c = new Customer("John Doe")
if (!c.save())
fail "validation failed: ${c.errors}"
Customer c2 = Customer.get(c.id)
c2.delete()
assertNull Customer.get(c.id)
def customers = Customer.findAllByName(“Fred”)
4/3/11 Copyright (c) 2011 Chris Richardson. All rights reserved.
Slide 35
36. Commentable plugin example
class CommentableGrailsPlugin {
def doWithDynamicMethods = { ctx ->
for(domainClass in application.domainClasses) {
if(Commentable.class.isAssignableFrom(domainClass.clazz)) {
domainClass.clazz.metaClass {
'static' {
getRecentComments {-> … }
}
addComment { poster, String text -> }
getComments = {-> }
…
}
4/3/11 Copyright (c) 2011 Chris Richardson. All rights reserved.
Slide 36
37. Grails DSL for ORM
class Customer {
static transients = ["networth"]
static mapping = {
id column: ‘customer_id’ Closures
table ‘crc_customer’
columns {
}
name column: ‘customer_name’ Method
} missing
def getNetworth() { … }
}
...
4/3/11 Copyright (c) 2011 Chris Richardson. All rights reserved.
Slide 37
38. Grails Controllers -
o Accessing request/response
o Databinding
n b.properties = params
n new B(params)
o …
4/3/11 Copyright (c) 2011 Chris Richardson. All rights reserved.
Slide 38
39. Agenda
o Evolution of programming languages
o Favorite Groovy features
o The frustration of using Groovy
o Scala: expressiveness and compile-
time checking
o The trouble with Scala
4/3/11 Copyright (c) 2011 Chris Richardson. All rights reserved.
Slide 39
40. Getting complex Groovy code to
work can be frustrating
o Dynamic language = less information
for IDE:
n Limited compile-time checking
n Limited refactorings
n Limited completion
n No todo list of errors
4/3/11 Copyright (c) 2011 Chris Richardson. All rights reserved.
Slide 40
41. Groovy fans say "write unit tests“
BUT…
Groovy
When you have typos
versus
Java
4/3/11 Copyright (c) 2011 Chris Richardson. All rights reserved.
Slide 41
42. Unit tests don't always catch errors
void testPollStatus_discoveringNewServer() {
mockEC2RequestExecutor.demand.executeRequest {params ->
….
}
def mockEC2Server = new MockFor(EC2Server.class)
….
mockEC2Server.use {
mockEC2RequestExecutor.use {
ec2 = new EC2(awsProperties)
ec2.pollStatus() public class EC2 {
assertEquals 1, ec2.servers.size()
} public pollStatus() {
} def params = ['Action':
} 'DescribeInstances']
def p =
requestor.executeRequest(params)
class EC2RequestExecutor { …
}
public Node executeEc2Request(Map …
parameters) { } Method signature changes are
… often missed
}
Slide 42
4/3/11 Copyright (c) 2011 Chris Richardson. All rights reserved.
43. The trouble with duck typing
o Interface between components not
defined in a single place
o It is scattered throughout callers
o Difficult to understand
o Difficult to change
4/3/11 Copyright (c) 2011 Chris Richardson. All rights reserved.
Slide 43
44. The outcome: fear of change
Did my tests
catch all
the obvious errors?
4/3/11 Copyright (c) 2011 Chris Richardson. All rights reserved.
Slide 44
45. Agenda
o Evolution of programming languages
o Favorite Groovy features
o The frustration of using Groovy
o Scala: expressiveness and
compile-time checking
o The trouble with Scala
4/3/11 Copyright (c) 2011 Chris Richardson. All rights reserved.
Slide 45
46. Distilling a language
Builders
Dynamic methods
and properties
Gpath-based
XML handling
Dynamic features
Static features
Closures
Groovy
Literals for
collections
GStrings
4/3/11 Copyright (c) 2011 Chris Richardson. All rights reserved.
Slide 46
47. Scala – a modern (2003) static
language
o Object-oriented
n Pure object-oriented language
n All values are objects “I can honestly say if someone had
n Class-based shown me the Programming in
Scala book by by Martin Odersky,
o Functional Lex Spoon & Bill Venners back in
n Functions are values 2003 I'd probably have never
created Groovy.”
n Higher-order functions
n Currying James Strachan, Creator of Groovy
http://macstrac.blogspot.com/
o Statically typed 2009/04/scala-as-long-term-
n Expressive replacement-for.html
n Type inference
o Extensible to support domain specific languages
n Methods as infix and postfix operators
n Automatic closure construction
4/3/11 Copyright (c) 2011 Chris Richardson. All rights reserved.
Slide 47
48. The good news
o Fully interoperable with Java
o Interactive shell
o Rich, extensible language
o Closures
o Good XML processing
o Named arguments and default
parameter values
o Option class avoids null references
o Traits provide “multiple inheritance”
4/3/11 Copyright (c) 2011 Chris Richardson. All rights reserved.
Slide 48
49. Scala command line
4/3/11 Copyright (c) 2011 Chris Richardson. All rights reserved.
Slide 49
50. Simple example
object StringFunctions {
def reverseSentence(sentence : String) = sentence.split(" ").reverse.mkString(" ")
}
import org.junit._
import Assert._
@Test
class StringFunctionsTest {
@Test
def testReverseSentence() = {
val input = "Hello New York"
val expected = "York New Hello"
assertEquals(expected, StringFunctions.reverseSentence(input))
}
}
4/3/11 Copyright (c) 2011 Chris Richardson. All rights reserved.
Slide 50
51. Collection literals example
@Test
class ScalaCollectionExamplesTest {
@Test
def listExample() = {
val myList = List(1, 2, 3)
assertEquals(3, myList.length)
assertEquals(List(0, 1, 2, 3), 0::myList)
assertEquals(List(2, 3), myList.tail)
assertEquals(1, myList.head)
}
@Test
def testMapExampleList() : Unit = {
val myMap = Map( "x" -> 1, "y" -> 2, "z" -> 3)
assertEquals(1, myMap("x"))
}
}
4/3/11 Copyright (c) 2011 Chris Richardson. All rights reserved.
Slide 51
52. Closure example
@Test
class ScalaCollectionExamplesTest {
@Test
def testMapList() = {
val myList = List(1, 2, 3)
assertEquals(List(2,4,6), myList.map ( x => x * 2))
assertEquals(List(2,4,6), myList.map ( _ * 2))
}
@Test
def testFilterList() = {
val myList = List(1, 2, 3)
assertEquals(List(1, 3), myList.filter( _ % 2 == 1));
}
}
4/3/11 Copyright (c) 2011 Chris Richardson. All rights reserved.
Slide 52
53. Defining new control constructs 1
class ExampleControlConstructExampleTest {
def withOutputStream[T](f : File)(body : InputStream => T) = {
val fis = new FileInputStream(f)
try {
body(fis)
} finally {
fis.close
}
}
@Test
def withOpenFileExample {
withOutputStream(new File("/Users/cer/.bashrc")) {fis =>
println(fis.available)
}
}
4/3/11 Copyright (c) 2011 Chris Richardson. All rights reserved.
Slide 53
54. Defining new control constructs 2
By-name parameter
var assertsEnabled = false
def myAssert(message : String, assertion : => Boolean) {
if (assertsEnabled) {
if (!assertion)
throw new RuntimeException(message)
}
}
@Test
def assertionsDisabled = {
myAssert("never", { println("you will not see me") ; false })
}
4/3/11 Copyright (c) 2011 Chris Richardson. All rights reserved.
Slide 54
55. Pattern matching
case class Organization(name: String,
industry: Industry.Value, revenue: Double, assets: Double, liabilities: Double) {
}
object Industry extends Enumeration {
val Banking, GreenEnergy, IT, Other = Value
}
class LoanApprovalPolicy {
def isLoanApproved(organization : Organization) = organization match {
case Organization(_, Industry.GreenEnergy, _, _, _) => true
case Organization(_, Industry.Banking, _, assets, liabilities)
if liabilities < assets * 1.5 => true
case Organization(_, Industry.Banking, _, _, _) => false
case Organization(_, _, _, assets, liabilities) if assets > liabilities => true
case _ => false
}
}
4/3/11 Copyright (c) 2011 Chris Richardson. All rights reserved.
Slide 55
56. XML generation
@Test
class ScalaXmlExampleTest {
@Test
def xmlLiterals() {
val now = new Date()
val loanRequestor =
new Organization("Community Bank, Inc", Industry.Banking, 10, 10, 5)
val doc = <loanRequest>
<time>{now.getTime()}</time>
<requester>{loanRequestor.name}</requester>
<industry>{loanRequestor.industry}</industry>
<revenue>{loanRequestor.revenue}</revenue>
<assets>{loanRequestor.assets}</assets>
<liabilities>{loanRequestor.liabilities}</liabilities>
</loanRequest>
val docAsString : String = doc.toString()
println(docAsString)
}
4/3/11 Copyright (c) 2011 Chris Richardson. All rights reserved.
Slide 56
57. XML parsing
class ScalaXmlExampleTest {
@Test
def xmlProcessing() {
val doc = xml.XML.loadString(docAsString)
assertEquals ("Community Bank, Inc", (doc "requester").text)
doc match {
case <loanRequest>{children @ _* }</loanRequest> =>
for (x <- children if !x.isInstanceOf[scala.xml.Text]) {
processChildren(x)
}
}
}
def processChildren(node : scala.xml.Node ) = {
node match {
case <time>{value}</time> => println(value.text)
case <requester>{value}</requester> => println(value.text)
…
}
}
4/3/11 Copyright (c) 2011 Chris Richardson. All rights reserved.
Slide 57
58. DSL Example
class OrganizationDslTest {
val o : Organization = (Organization
called "Bernie Madoff & Associates"
in Industry.Banking
withRevenuesOf (10 million)
withAssetsOf (10 billion)
withLiabilitiesOf (30 billion))
}
object Organization {
def called(name : String) = new OrganizationBuilder(name)
class OrganizationBuilder(name : String) {
var industry : Industry.Value = null
def in(industry : Industry.Value) = { this.industry = industry; this }
def withRevenuesOf(…) = …
…
def make()= new Organization(name, industry, revenue, assets, liabilities)
}
implicit def organizationBuilderToOrganization(builder : OrganizationBuilder)
= builder.make
}
4/3/11 Copyright (c) 2011 Chris Richardson. All rights reserved.
Slide 58
59. Named arguments and default values
o Arguments can be named
o Parameters can have default values
o Benefits:
n Clearer code – Booleans aren’t so evil
n Avoids confusing overloaded methods/
constructors
n Less need for the Builder pattern
def foo(x: Int = 10, y: Int = 20) = x * y
foo() should be(200)
foo(y = 30, x = 50) should be(1500)
foo(x = 50) should be(1000)
4/3/11 Copyright (c) 2011 Chris Richardson. All rights reserved.
Slide 59
60. Constructing object hierarchies
object ExampleSwingApp extends SimpleGUIApplication {
def top = new MainFrame {
title = "Example Swing App" Defines method declared
abstract in superclass
val button = new Button {
text = "press"
} Sets property
contents = button
var count = 0 Statements/
listenTo(button)
reactions += { expressions that
case ButtonClicked(b) => are executed
count = count + 1
Console.println(count);
b.text = "press: " + count Nesting of new Class {
}
} }
mirrors object hierarchy
}
4/3/11 Copyright (c) 2011 Chris Richardson. All rights reserved.
Slide 60
61. Pimping existing classes
scala> 5.times { println("Hello") }
<console>:6: error: value times is not a member of Int
5.times { println("Hello") }
^
scala> class IntWithTimes(n: Int) {
| def times(body: => Unit) = for (x <- 1 to n) body
| }
defined class IntWithTimes
scala> implicit def toIntWithTimes(n: Int) = new IntWithTimes(n)
toIntWithTimes: (n: Int)IntWithTimes
scala> 5.times { println("Hello") }
Hello
Hello
Hello Implicit conversion
Hello
Hello
4/3/11 Copyright (c) 2011 Chris Richardson. All rights reserved.
Slide 61
62. Implicit parameters 1
@Test
def implicitParamsImplicitVar {
implicit val defaultValue = 8
def m(i : Int) (implicit j : Int) = i * j
assertEquals(48, m(6))
assertEquals(42, m(6)(7))
}
4/3/11 Copyright (c) 2011 Chris Richardson. All rights reserved.
Slide 62
63. Implicit parameters 2
scala> implicit def toInt : Int = 5
toInt: Int
scala> def m(i : Int) (implicit j : Int) = i * j
m: (i: Int)(implicit j: Int)Int
scala> m(6)
res6: Int = 30
scala> m(6)(7)
res7: Int = 42
4/3/11 Copyright (c) 2011 Chris Richardson. All rights reserved.
Slide 63
64. Null References
My Billion Dollar
mistake
4/3/11 Copyright (c) 2011 Chris Richardson. All rights reserved.
Slide 64
65. Use Options instead of null…
var x : Option[Int] = Some(5)
var y : Option[Int] = None
var z : Option[Int] = Some(7)
assertEquals(5, x.get)
try {
y.get
fail
} catch {
case _ : NoSuchElementException =>
}
assertEquals(5, x.getOrElse(10))
assertEquals(10, y.getOrElse(10))
4/3/11 Copyright (c) 2011 Chris Richardson. All rights reserved.
Slide 65
66. … more options
assertEquals(Some(7), x.map(_ + 2))
assertEquals(None, y.map(_ + 2))
assertEquals(None, x.filter(_ == 2))
assertEquals(Some(5), x.filter(_ == 5))
assertEquals(Some(35),
for (a <- x ; b <- z) yield a * b)
4/3/11 Copyright (c) 2011 Chris Richardson. All rights reserved.
Slide 66
67. Traits
o Consist of members
n methods
n fields
n types
o The members can be abstract
o Multiple traits can be mixed into a class
n Alternative to multiple inheritance
n Class must define abstract members
o Uses:
n Modularizing applications
n Enriching interfaces
n Decorating classes
4/3/11 Copyright (c) 2011 Chris Richardson. All rights reserved.
Slide 67
68. RESTful WS using Spring MVC and
Scala
o Handling HTTP request Photo management
n Extract values from URL
n Invoke appropriate handler
application
n Generate response (XML)
o Sounds like a job for Scala's GET /album
n Pattern matching GET /album/<albumId>
n XML support POST /album
…
<album>
<id>6699</id>
GET /album/6699 <photos>…</photos>
…
</album>
4/3/11 Copyright (c) 2011 Chris Richardson. All rights reserved.
Slide 68
69. Pattern matching HTTP Requests
o Match against
n URL – represented as a List
n Method
n …
o Returns XML
request match {
case Request(List("album"), "GET", _, _) =>
listAlbums
case Request(List("album", albumId), "GET", _, _) =>
findAlbum(albumId)
}
def findAlbum(albumId : String) = {
def album = albumService.findAlbum(albumId)
<album>
<id>{album.getId()}</id>
<photos>…</photos>
…
</album>
}
4/3/11 Copyright (c) 2011 Chris Richardson. All rights reserved.
Slide 69
70. The Extractor
object Request {
def unapply(request : HttpServletRequest)
: Option[ (List[String], String, RequestBody, Binder)]
={
val path =
List.fromArray(request.getPathInfo().split("/")).tail
Some(path,
request.getMethod,
new RequestBody(request),
new Binder(request))
}
}
4/3/11 Copyright (c) 2011 Chris Richardson. All rights reserved.
Slide 70
72. Integrate with Spring MVC 1
@Component
class WsEndpointHandlerMapping extends HandlerMapping {
@Autowired
def setApplicationContext(applicationContext : ApplicationContext) {
this.applicationContext = applicationContext
}
def endpoints = …applicationContext.getBeansOfType(classOf[WsEndpoint])…
override def getHandler(request : HttpServletRequest) : HandlerExecutionChain = {
val endpointForRequest = endpoints.find( _.isDefinedAt(request))
endpointForRequest match {
case Some(endpoint) => new HandlerExecutionChain(endpoint)
case None => null
}
}
Maps HTTP request to WSEndpoint
4/3/11 Copyright (c) 2011 Chris Richardson. All rights reserved.
Slide 72
73. Integrate with Spring MVC 2
@Component
class WsEndpointHandlerAdapter extends HandlerAdapter {
override def supports(handler : Object) = {
handler.isInstanceOf[WsEndpoint]
}
override def handle(request : HttpServletRequest ,
response : HttpServletResponse , handler : Object ) : ModelAndView = {
val endpoint = handler.asInstanceOf[WsEndpoint]
val node = endpoint(request)
response.setContentType("text/xml")
response.getWriter.print(node.toString)
null
}
Invokes WSEndpoint and generates HTTP response
4/3/11 Copyright (c) 2011 Chris Richardson. All rights reserved.
Slide 73
74. Scala and Spring DI
o Scala and Spring DI play together
o @Component on Scala classes works
o @Autowired fields:
n Annotation ends up on field and
generated methods è fail
n Need to define and annotate setters
4/3/11 Copyright (c) 2011 Chris Richardson. All rights reserved.
Slide 74
75. Agenda
o Evolution of programming languages
o Favorite Groovy features
o The frustration of using Groovy
o Scala: expressiveness and compile-
time checking
o The trouble with Scala
4/3/11 Copyright (c) 2011 Chris Richardson. All rights reserved.
Slide 75
76. Really bad news
o Scala IDEs are ok and slowly
improving BUT have a really really
long way to go compared to Java
o Limited refactoring => painful to
maintain code quality?
4/3/11 Copyright (c) 2011 Chris Richardson. All rights reserved.
Slide 76
77. More bad news…
o Expressiveness comes from complex
language features
o Generics are better than Java but still
complex
BUT
o The investment in learning these
features is repaid with every
application you write
4/3/11 Copyright (c) 2011 Chris Richardson. All rights reserved.
Slide 77
78. …more bad news
o Lift is not Grails (or Rails)
o A subset of the Scala community has
a functional programming background
=> Obsessed with their Monads
o Implicit conversions make it possible
to write “incomprehensible” code
o Scala Collections != Java Collections
n BUT Implicit conversions simplify
interoperability
4/3/11 Copyright (c) 2011 Chris Richardson. All rights reserved.
Slide 78
79. Summary
o The Java Language has stagnated and
need to be replaced
o Dynamic languages are one option
o But many benefits of those languages
are due to good language design
o Scala = expressiveness + static typing
o But Grails derives much of its power
from the dynamic features of Groovy
o Therefore, choose the right tool:
n Web application è Use Groovy and Grails
n Complex business logic/middleware è
Consider Scala
4/3/11 Copyright (c) 2011 Chris Richardson. All rights reserved.
Slide 79
80. Summary – Pessimistic view
o Languages used by mainstream
developers have improved
substantially
o But are those languages that much
better than the 25+ year old “ivory
tower” languages: LISP, Smalltalk,
ML, … ?
4/3/11 Copyright (c) 2011 Chris Richardson. All rights reserved.
Slide 80
81. Final thoughts
o Learn some languages including
Haskell
o Watch the 50 in 50 presentation by
Guy Steele and Dick Gabriel:
http://blog.jaoo.dk/2008/11/21/art-
and-code-obscure-or-beautiful-code/
"Those who cannot remember the past
are condemned to repeat it”
http://en.wikipedia.org/wiki/George_Santayana
4/3/11 Copyright (c) 2011 Chris Richardson. All rights reserved.
Slide 81
82. The end
Twitter:
@crichardson
Send email:
chris@chrisrichardson.net
4/3/11 Copyright (c) 2011 Chris Richardson. All rights reserved.
Slide 82