You are on page 1of 66

Dynamic Languages for

the Java Virtual Machine
Lee Chuk Munn
Staff Engineer
1
Objective

Survey of Dynamic
Languages on the
JVM
Groovy, Ruby, Scala, Clojure

2
What to (Not) Expect
> Discussion on a small > “Hello World”
subset of the languages > Coverage of all features
> Highlight interesting > Which is a 'better'
language features language
> How the features are used > An apple to apple
> Contrast with Java comparison
> Java bashing

3
Groovy
groovy.codehaus.org/

4
Language Features – 1
> Object oriented programming language
> Syntax is very similar to Java – feels very much like Java
• Runs Java sources files
> Compact and concise syntax
• Optional semi colon and parenthesis
• Native syntax for list, maps and regex
> Seamless bi directional integration with Java
• Groovy extending Java class implementing Groovy interfaces
• Reuse Java's infrastructure – classes, security, threads, etc
> Closure, properties and operator overloading support
> Builder library to easily created nested data

5
Language Features – 2
> Easy integration with Java application with JSR-223
• Only one JAR – embeddable/groovy-all-1.x.y.jar
­ Probably one of the best feature
> MOP provides the meta programming capabilities
• A runtime layer which any application can participate

6
A Valid Java Program
import java.util.*;
public class Erase {
private List<String> filterLongerThan(List<String> list, int len) {
List<String> result = new ArrayList<String>();
for (String n: list)
if (n.length() <= len)
result.add(n);
return (result);
}
public static void main(String... args) {
List<String> names = new ArrayList<String>();
names.add(“Fred”); names.add(“Barney);
names.add(“Wilma”); names.add(“Betty”);
System.out.println(names);
Erase e = new Erase();
List<String> shortNames = e.filterLongerThan(names, 5);
System.out.println(shortNames);
}
}
7
A Valid Groovy Program
import java.util.*;
public class Erase {
private List<String> filterLongerThan(List<String> list, int len) {
List<String> result = new ArrayList<String>();
for (String n: list)
if (n.length() <= len)
result.add(n);
return (result);
}
public static void main(String... args) {
List<String> names = new ArrayList<String>();
names.add(“Fred”); names.add(“Barney);
names.add(“Wilma”); names.add(“Betty”);
System.out.println(names);
Erase e = new Erase();
List<String> shortNames = e.filterLongerThan(names, 5);
System.out.println(shortNames);
}
}
8
Groovy Way
Automatically imports java.util.*

Native list syntax

def names = ["Ted", "Fred", "Jed", "Ned"]
Creates an ArrayList
println names

def shortNames = names.findAll { Closure support
it.size() <= 3
}

def diff = names - shortNames
print diff
Operator overloading

9
Example – A Groovy Class
public class Person { Map literal
def props = [:]
Statically type
String name Interpolated string
int age = 45 Weakly type
def email
String toString() { “${name}, ${age}, ${gender}“}
Object get(String n) { props[n] }
void set(String n, Object v) { props[n] = v }
}
Dynamic properties

Person fred = new Person(name: 'Fred'
, email: 'fred@bedrock.com')
Constructor with
property/keyword
fred.gender = 'male' parameters

Adding a property dynamically
10
Operator Overloading
> Every operator can be overloaded via corresponding
method
• Eg. plus() for '+', leftShift() for '<<', etc.
> Special method for switch classification
• Override isCase()
Person fred = …
public class Family {
def members = [] Person wilma = …
def plus(Person o) { Family flintstones = …
members += o flintstone += fred + wilma
members
} Person barney = …
def plus(Family f) { Person betty = …
members += f.members Family rubble = …
members
rubble += barney + betty
}
}
11
Category
> Add temporary methods or behaviour to instances of
object code block
class StringCalcutation {
static def plus(String self, String operand) {
try {
return (self.toInteger()
+ operand.toInteger()).toString()
} catch (NumberFormatException f) {
return (self << operand)
}
}
}

println “43” + “43” → “4343”
use(StringCalculation) { Redefine the behaviour
of + in code block
println “43” + “43” → “86”
} Example adapted from Groovy in Action by Dierk Konig et al 12
Closure
> A piece of code that is wrapped in an object
• Anonymous functions/methods
Takes 2 parameters.
• Behaves like data, but can be invoked Closure has a default
value

def perform(int times, Closure c = {}) {
for (i = 0; i < times; i++)
c.call(i)
}

perform(3) { x -> println “hello: ${x}” }

Parameter Code block not executed but
pass to perform a parameter
13
Example – New Controls with Closure
def withLock(Lock l, Closure c) {
l.lock();
try {
c.call()
} finally {
l.unlock();
} Closure runs in the context of lock
}
Lock lock = new ReentrantLock()
withLock(lock) { println “I have acquired the lock” }

Closure with parameters
def logInfo = { logger, msg -> logger.log(Level.INFO, msg) }
withLock(lock
, logInfo.curry(Logger.getLogger("groovy")).curry("Hello"))

Use curry to wrap parameters
14
Meta Object Protocol
> Provides dynamic behaviour to Groovy
• Intercept method calls, create classes and methods, etc
> MOP consists of
• Formalized behaviour for resolving methods/properties
• Two major classes: GroovyObject and MetaClass
> Override methods in MetaClass to redefine behaviour
String.metaClass.constructor = { Replace the default
constructor = constructor
String.class.getConstructor(String.class)
constructor.newInstance((new Date()).toString())
}

println new String() → “Sat Nov 21 ...”

> Lots of libraries uses MOP
Example adapted from Groovy in Action by Dierk Konig et al 15
Example – ExpandoMetaClass
> Expando class allows developers to add methods to an
object dynamically
> Two variants
• Expando
• ExpandoMetaClass

def person = new ExpandoMetaClass(Person)
person.isAdult = { age >= 18 }

if (person.isAdult())
...

16
Example – D&D Style Die Roll
Integer.metaClass.getProperty = { String sym ->
//Check if sym is in 'd<digit><digit>' format
if (!(sym ==~ /^d\d+$/))
return (-1)
def face = sym.split(/d/)[1].toInteger()
def rand = new Random()
def result = []
delegate.times {
result += (Math.abs(rand.nextInt()) % face) + 1
}
result
}
//D&D style dice roll
println 5.d10
[2, 7, 5, 4, 10]
17
Ruby
www.ruby-lang.org

18
Language Features
> Supports multiple programming paradigm
• Imperative, object oriented, functional and reflective
> Excellent support for reflective programming /
metaprogramming
• Ruby re-introduce to developers
> Continuation support
• Freeze a point in the application and return to it later
> Supports reuse through inheritance, mixins and open
classes
• Open classes is the ability to modify and existing class including
those from the host library
­ Eg. add rot13() method to java.lang.String

19
Example – A Ruby Class
Class member Create getter/setter for
class Song
@@plays = 0 members
attr_accessor :name, :artist, :duration
def initialize(n, a, d) Denotes symbol
@name = n; @artist = a; @duration = d
end
def duration_in_minutes
@duration / 60
end Instance member
def duration_in_minutes=(v)
@duration = v * 40
end Methods
def play
@@plays += 1
end
end
20
Example – A Ruby Session
s = Song.new("Cavatina", "John Williams", 200)
puts s
#<Song:0x9dca26>

s.duration_in_minutes = 4
s.play
Adding a new method to class
class Song 
def to_s
"song = #{@name}, artist = #{@artist}, duration = 
#{@duration}, plays = #{@@plays}"
end
end

puts s
song = Cavatina, artist = John Williams, duration = 200, 
plays = 1
21
Objects and Method Calls
> Everything in Ruby is an object
• Objects, things that look like primitive and classes

s = Song.new Invoking the new method on
the Song object
> Everything is a method call
• Message passing masquerading as method calls
• obj.fred is the same as obj.send(:fred)as
­ Method invocation means sending a message to the object
­ Use respond_to? to inspect if an object supports a particular message
• Methods can be invoked with our without parenthesis
­ Excellent for readability and DSL

x = 1 + 2 – 3 is equivalent to x = 1.+(2.send(:+, 3))

puts ugly_d.quack if ugly_d.respond_to? :quack
22
Reuse
> Inheritance – traditional OO way Inherit from Song
class KaraokeSong < Song
... This means super.to_s – from
def to_s context
super + “[#{@lyrics}]”
end
> Mixins – adding a module into a class or object
• Cannot be instantiated Mixin to class
or instance
module ClassName class Song
def class_name include ClassName
self.class.name
end s = Song.new(...).extend(ClassName)
end

> Open classes – adding methods to class or object
class String
def rot13
self.tr(“A-Ma-mN-Zn-z”, “N-Zn-zA-Ma-m”)
end
end 23
Metaprogramming with Ruby
> Technique by which a program can manipulate another
program or itself as their data
> Ruby relies on metaprogramming heavily
• Eg. in declaring properties
> Introspect into a a class, object or the running environment
• Eg. ObjectSpace.each_object(String) {|x| puts x}
> Allows you to trap interesting behaviour and override or
enhance them
• Similiar AOP
• Eg. creating a method, instantiating an object, invoking a missing
method, querying if a member is defined, etc.
• Eg. emulate ExpandoMetaClass in Groovy by trapping
undefined method names

24
Example – Object Instantiation
> Set the creation time on an object if the object has a
property call timestamp
Rename new to old_new

class Class Provide our own 'new'
alias_method :old_new, :new
def new(*args)
result = old_new(*args)
result.timestamp = Time.now if defined?(result.timestamp)
result
end
end
Set the time if timestamp exists

Example adapted from “Programming Ruby 2nd Edition by Dave Thomas” 25
Example – Implementing ExpandoMetaClass
> A Groovy feature that allows you to add methods to
instances on the fly
Add the method to
class ExpandoMetaClass instance
def method_missing(name, *args)
if args[0].is_a?(Proc)
self.class.instance_eval do
define_method(name.to_s.chomp("="), args[0])
end
else
super class Foo < ExpandoMetaClass
end end
end
end f = Foo.new
f.greet = lambda {|t| "Hello #{t}!"}
f.greet "Fred"
26
Example – JavaBean Style Properties
class Module
def java_bean(*syms)
syms.each do |s|
pn = s.to_s.split("_").collect!{|x| x.capitalize}.join
class_eval %{
def get#{pn}
@#{pn} class Demo
end java_bean :my_name
} …
class_eval %{
end
def set#{pn}(v)
@#{pn} = v
end demo = Demo.new
} demo.setMyName(“fred”)
end puts demo.getMyName
end
end

Caution: This will probably infuriate Rubyists 27
Continuations
> Abstract representation of “the rest of the code to be
executed”
if (i > 10) The continuation of “if (i > 10)” is
puts “i > 10”
puts “i > 10” iff i > 10
else
puts “i < 10” puts “i < 10” iff i < 10
end
> Uses of continuations
• Coroutines, escape and reenter loops/recursion, debugger, need
to backtrack
• See
http://repository.readscheme.org/ftp/papers/PLoP2001%5Fdfer
guson0%5F1.pdf
• Eg. Able to return to the point of exception after handling the
exception

28
callcc
> callcc to construct a continuation object in Ruby
• Encapsulates the state of the application up to callcc
• Use the continuation object to jump to just after the callcc

result = 1
i = 1
callcc {|$cont_obj|}

Ruby passes a continuation
result *= i object to block
i += 1
$cont_obj.call if (i <= 10)

Returns to the statement just
after the callcc
29
Example – Coroutine 1
def ping
puts "PING 1"
save_and_resume($ping_cont,
pong
nil)
PING 1
puts "PING 2"
save_and_resume($ping_cont, $pong_cont)
PONG 1
puts "PING 3" PING 2
save_and_resume($ping_cont, $pong_cont)
end PONG 2
def pong
puts "PONG 1" PING 3
save_and_resume($pong_cont,
puts "PONG 2"
$ping_cont)
PONG 3
save_and_resume($pong_cont, $ping_cont)
puts "PONG 3"
save_and_resume($pong_cont, $ping_cont)
end
ping
Example adapted from “Call with Current Continuation
Patterns” by Darrell Ferguson, Dwight Deugo 30
Example – Coroutine 2

Create a current continuation
for the current location

def save_and_resume(save_cont, resume_cont)
callcc {|save_cont|}
resume_cont.call unless resume_cont == nil
end

Resume the other routine

31
Scala
www.scala-lang.org

32
Language Features – 1
> A hybrid of object and functional
• Supports mutable and immutable (functional) structures
• Defaults to immutable for collections
> Objects, singletons and traits
• Singleton is a language concept
• Very similar to interfaces but with fully implemented methods
­ Cannot be instantiated, can only be mixed into a class or object
• Supports operator overloading
­ Operators are all method calls
> Statically typed – unique in the world of script language
• Can infer types from code during declaration
• Easily implement new types and corresponding operations
• Supports user define implicit type conversion

33
Language Features – 2
> Statically typed higher order functions
• More rigorous in what you can pass to a method
> Supports many high level concurrency abstraction
• Monitors, atomic variables, semaphores, workers, channels, etc
• Erlang style actors

34
Statically Typed
> Must provide type in method definition
• Elsewhere Scala can infer type from the context
­ var map = Map[Int, String](1 -> “Cat”, 2 -> “Dog”)
• Method return type, variable declaration
> Including closure / functions types
• var myfunc: ((Int, Int) => Complex) = null

Method declaration
def sumOfFactors(number: Int): Int = {
var sum = 0
for (i <- 1 to number)
Inferring from
if ((sum % i) == 0) context
sum += i
sum
}
35
Defining Classes
The minimal class
class Person(val name: String)
Default constructor
class Employee(override val name: String
, val id: String) extends Person(name) {
var salary: Double = _
def this(name: String, id: String, _salary: Double) {
this(name, id)
salary = _double Overloaded constructor
}
def calculateSalary() = {
salary
}
override def toString(): String = name + “(“ + id + “)”
}

var fred = new Employee(“James”, “007”)
println(fred name) //Equivalent to fred.name 36
Singletons
> Refer to as companion objects in Scala
• Use extensively in Scala class libraries
> Defined in the same file as the class
• Can access private constructors
object Employee {
def apply(name: String, id: String) Curried function
= new Employee(name, id)
def apply(name: String, id: String, salary: Double)
(verify: (String, String, Double)=> Option[Employee])
Singleton :Option[Employee] = {
if (verify(name, id, salary))
Some(new Employee(name, id, salary))
else
Closure's signature
None
}
} Option indicates we may not
be getting any result 37
Example – Singletons as Factories

var fred = Employee(“Fred”, “007”)

var obj = Employee("Barney", "001", 12000)
{(name, id, salary) => (salary <= 10000)}
Return type is not Employee
Curried function so
var barney: Employee closure appears outside
if (obj.isEmpty) { of formal parameter list
println("Salary is too high")
} else {
barney = obj.get
}

38
Traits
> Similar to interfaces with partial implementations
trait Greetings {
def sayHello(name: String) = “Hello “ + name
}

> Mixed in to classes or selectively to object instances
• Mixin to class
class Employee(override val name: String, val id: String)
extends Person(name) with Greetings {

• Mixin to instance
­ Only applicable if there are no abstract methods

val fred = new Employee(“Fred”, “007”) with Greetings

39
Selective Mixin
> Can enforce mixing traits only into certain classes
• By extending from a class
> Late binding with super object
> Resolution of super proceeds from right to left
• Eg class A extends B with TraitA with TraitB
• TraitB → TraitA → A – assuming B is a class
• Excellent for implementing decorator or chain-of-command
pattern

40
Example – Selective Mixin – 1
class Person(val name: String) {
def calculateSalary(base: Double) = base
}
class Employee(...) extends Person(...) {
def mySalary() = calculateSalary(salary)
... Can only be mixin to
} classes that extends
trait SpotBonus extends Person { from Person
override def calculateSalary(base: Double) =
super.calculateSalary(base + (base * 0.05))
}

trait ThirteenMonth extends Person {
override def calculateSalary(base: Double) =
super.calculateSalary(base + base)
}

41
Example – Selective Mixin – 2

val fred = new Fred(“Fred”, “007”, 5000)
with AnnualLeave with ThirteenMonth

println(“salary = “ + fred.mySalary)

Resolution goes from right to left
Fred.mySalary
ThirteenMonth.calculateSalary
AnnualLeave.calculateSalary
Fred.calculateSalary

42
Operators on Types
> All method calls, no notion of operators
• Operator precedence is based on ordering of symbols
• Eg. all letters, |, ^, &, < >, = !,:, + -, * % /, all other
special characters
• Unary operators, prefixed with unary_
class Employee(override name: String ... //As before
def +(_salary: Double) = this.salary + _salary
def -:(_salary: Double) = this.salary - _salary
def unary_>>!(): Employee = ... //promotion
def unary_<<!(): Employee = ... //demotion

fred.salary = fred + 1000 //Method call fred.+(1000)
fred >>! //promote fred
100 -: fred

Instance to follow method
43
Implicit Type Conversion
> Most language have build in implicit conversion
• Eg. byte + int – byte is converted to int
> Scala allows you to define implicit conversion
• Use implicit keyword on method
var yesterday = 1 days ago Converter that takes 1 and
return ???.days(“ago”)
class DateHelper(num: Int) {
def days(when: String) = {
var date = Calendar.getInstance()
when match {
case “ago” => date.add(Calendar.DAY_OF_MONTH, -num)
...
}
date.getTime()
}
}
def implicit convertInt2DateHelper(num: Int) = new DateHelper(num)
*
Adapted from Programming Scala by Venkat Subramaniam 44
Concurrency
> Lots of abstraction to support concurrency and asynchrony
• Signals, monitors, atomic objects, semaphores, workers, mail
boxes, actors etc
> Actor based model
• A computation entity that inherently concurrent
• Communicate by send it messages
• Can change its state or spawn new actors based on messages
> Two ways of using actors
• actor method
• Extend Actor class
> Communications
• ! to send a message
• receive – case to select message based on type

45
Determining a Prime Number
> Is x a prime number?
> Does x have a factor in the range of 3 to (x – 1)?
> Eg. Is 97 a prime number?
• Are there any factors in 3 to 96
> For larger number, partition range and find factors in
parallel
> Eg. 97, partition size of 20
• 3 – 22
• 32 – 42
• 43 – 62 97 is a prime number if there are no
factors in these ranges
• 63 – 82
• 83 – 96

46
Example – Determining Prime – 1
import scala.actors.Actor._
val caller = self
def haveFactorInRange(primSusp: Int, min: Int, max: Int): Boolean = {
((min to max).filter { x => ((primSusp % x) == 0) }.size != 0)
}
//No checking done
def isPrime(primSusp: Int): Boolean = {
val range = primSusp - 3
val partition = (range / 20) + (if ((range % 20) > 0) 1 else 0)
var haveFactor = false
for (i <- 0 until partition) {
val min = 3 + (i * 20) Creates an actor and
val max = if ((min + 19) > primSusp) starts it
(primSusp - 1) else (min + 19)
actor {
caller ! haveFactorInRange(primSusp, min, max)
}
} Execute the function and send
... the result to the collator 47
}
Example – Determining Prime – 2

def isPrime(basis: Int): Boolean = {
... Waits for messages
var haveFactor = false from actors
...
(0 until partition).foreach { x =>
receive {
case ans: Boolean =>
haveFactor = haveFactor || ans
case _ =>
}
}
Match the message type
against the discriminator
!haveFactor
}

48
Clojure
http://clojure.org

49
Language Features – 1
> Functional language
• Verb (functions) is the central theme, not noun (objects)
• No side effects – only depends on its arguments
­ Most Java method do not qualify as functions
• Give the same argument, will return the same result EVERYTIME
­ Functions are stateless
­ f(x) = f(y) if x is equals y
> Higher order functions
• f(x) → g(y) where x and y can be functions
• Closure is very natural
(defn make-greeter [greetings]
(fn [name] (format “%s, %s” greetings name)))
((make-greeter “Bonjour”) “Jean”) → “Bonjour, Jean”

Lambda Parameter Body 50
Language Features – 2
> All data is immutable – no data is ever change*
(def foo '(a b c)) → (a b c) Reassigned
(concat foo '(x y z)) → (a b c x y z)
foo → (a b c)
(def foo (concat foo '(x y z))) → (a b c x y z)
> Everything is a sequence – with abstractions
• List – (a b c)
• Vector – [a b c]
• Set – #{a b c}
• Map – {:x a, :y b, :z c}
> Homoiconic – the data structure is the language
• No language syntax – just have to know how to write parenthesis
• Evaluation rules – first element is the function name
­ Everything else are parameters
*except for refs
51
Calculate 10!
Java
public int fac(final int f) {
int tot = 1;
for (int i = 1; i < f; i++
tot *= i
return (tot);
Function defintion
}

Clojure
(defn fac [f]
(if (zero? f)
1
(* f (fac (dec f)))))
52
Calculating 10! with Sequences
> Create a list of values, apply a function over these value
• x! = (x – 1)! * x
(appy * (range 1 11))
(range 1 11) → (1 2 3 4 5 6 7 8 9 10)
(apply * (1 2 3 4 5 6 7 8 9 10))

> Lazy (is a virtue) and infinite sequences
• Infinite sequence that will only generate the next value iff required

;generate an infinite factorial list
(defn fac Generate an infinite
Overloaded function sequence of factorials
([] 1)
([x] (apply * (range 1 (inc x)))))
(defn fac-list [] (map fac (iterate inc 1)))
Take 5 from list
(take 5 (fac-list)) → (1 2 6 24 120) 53
Calling Java
> Importing Java classes
(import '(java.awt.event ActionEvent)
> Instantiating Java classes
(def f (new JFrame “Thisis a frame”))
(def f (JFrame. “This is a frame”))
> Accessing methods and members
(. f setVisible true)
(.setVisible f true)
(.getDefaultButton (.getRootPane f))
→ (.. f getRootPane getDefaultButton)
> Implementing interfaces and extending classes
• With type hints Type hint
(proxy [ActionListener][]
(actionPerformed [#^ActionEvent a-evt] ( … ))) 54
Creating a Swing Frame
;Import the relevant classes
(import
'(javax.swing JFrame JPanel JButton)
'(java.awt.event ActionListener
ActionEvent WindowAdapter WindowEvent))

;Implement an ActionListener Implements the
(def act-listener ActionListener
(proxy [ActionListener] []
(actionPerformed [a-evt]
(println (format "Button %s pressed"
(. a-evt getActionCommand))))
)
)

55
Creating a Swing Frame
;Create a button
(def button
(doto (JButton. "Press me")
(.addActionListener act-listener)))
;Create a panel
(def panel Apply all following
(doto (JPanel.) methods to the instance
(.add button)))
;Create a frame
(doto (JFrame.)
(.setTitle "Hello")
(.setDefaultCloseOperation JFrame/DISPOSE_ON_CLOSE)
(.add panel)
(.addWindowListener win-listener)
(.pack)
(.setLocationRelativeTo nil) Accessing static member
(.setVisible true))
56
Concurrency
> Supports 4 concurrency model
• Agents – actors but pass functions instead of messages
• Atoms – like java.util.concurrent.atomic
• References – database like transaction semantics
­ a.k.a Software Transaction Memory (STM)
• Vars – thread local
Agents Atoms References Vars
Shared X X X
Isolated X
Synchronous X X
Asynchronous X
Coordinated X
Autonomous X X
57
Sharing Data via Managed References
foo
Thread A
Data

bar Most programming languages
Thread B eg. Java, C, etc.

Thread A @foo
foo Data

Deference to access
Thread B immutable data
58
Agents
> Use to manage independent states
> Send functions to modify the state of the agent
• Functions are executed asynchronously
• Only one function is evaluated at a time
­ Some notion of ordering

(def foo (agent 0))
@foo → 0
(inc @foo) → 1 @foo is immutable
@foo → 0

(send foo inc)

... after some time ...
@foo → 1
59
References and STM
> References (ref) provide database like transaction
> Software transactional memory
• All or nothing
• Data are not visible until you commit
• All changes happens at constant time
­ You see all the changes at once
> No inconsistent data during transaction
• Thanks to Clojure's immutable data
> All references must occur in a transaction
• Create references with ref
• Use either alter or commute to change the ref
• dosync execute expressions in a transaction
­ alter and commute will only run in dosync

60
Using ref
(defstruct emp :id :name)
(def foo (ref (struct '123 “Fred”))) → {:id 123 :name “Fred”}
@foo → {:id 123 :name “Fred”}

(assoc @foo :gender 'male)
→ {:id 123 :name “Fred” :gender male}
@foo → {:id 123 :name “Fred”}
Create a transaction
(dosync
(alter foo assoc :gender 'male))
→ {:id 123 :name “Fred” :gender male}
(dosync
(commute foo assoc :gender 'male))
→ {:id 123 :name “Fred” :gender male}

@foo → {:id 123 :name “Fred” :gender male}
61
Handling Conflicts with alter
(dosync (alter foo assoc ...))

(assoc ...) (assoc ...)

time
foo alter by another transaction Transaction is retried
> At the start of the transaction
• Get an in transaction copy of foo's value (@foo)
• Value will never be inconsistent – data is immutable
> At the end of the transaction
• foo is check if it has changed during the transaction
-1
­ f (f(x)) = x where x is is the value of foo at the start of the transaction

• If it has, transaction is retried
­ Body of transaction must be side effect free
• Otherwise transaction commits → new value visible to all 62
Handling Conflicts with commute
(dosync (commute foo assoc ...))

(assoc ...) (assoc ...)

time
foo alter by another transaction Function is retried
> Same semantics as alter
• Except at the end of the transaction
• If foo is altered, the function is retried
> Function must be commutative and without side effects
• Eg. deposit is a commutative operation
­ You can invoke deposit in any order, the final state of the account will still
be consistent
­ Withdrawal is not commutative
63
Lee Chuk Munn
Staff Engineer
chuk-munn.lee@sun.com

64
64
Relational Algebra (or SQL)
> Nice set of relational algebra to work on sets
• Relational algebra is the basis of SQL

>

65
Immutable Data

(def x '(a b c)) a b c

x

(def y (rest x)) a b c

x y

(def z (into x '(d))) d a b c

z x y
66