porting java to scala
DESCRIPTION
In this talk we contrast and compare the interface of the Java Bindings with the development and design of the Scala bindings and interfaces, with particular reference to the introduction of Scala language specific features such as the use of Options and the Scala Actors model.TRANSCRIPT
![Page 1: Porting Java To Scala](https://reader034.vdocument.in/reader034/viewer/2022052410/554f970fb4c905ad218b46bb/html5/thumbnails/1.jpg)
http://www.casualmiracles.com/
DEVELOPING THE SCALA BINDINGS FOR THE FLY OBJECT SPACE
><----
--------->
<---->
Channing Walton [email protected]
Nigel Warren [email protected]
CM, Java experience, CRE, UCLPresentation about my experience porting from Java to Scala
![Page 2: Porting Java To Scala](https://reader034.vdocument.in/reader034/viewer/2022052410/554f970fb4c905ad218b46bb/html5/thumbnails/2.jpg)
http://www.casualmiracles.com/
INTRODUCTION
State safe co-ordination and communication between
distributed system components.
![Page 3: Porting Java To Scala](https://reader034.vdocument.in/reader034/viewer/2022052410/554f970fb4c905ad218b46bb/html5/thumbnails/3.jpg)
http://www.casualmiracles.com/
SPACES Tuple Spaces - Linda (a coordination language)
in - put a tuple into a space
rd – get a copy of a tuple from the space
out – remove tuple from the space
Subsequently …
Java Spaces - Jini – Java
Rinda – Ruby
PyLinda – Python
etc., etc.
![Page 4: Porting Java To Scala](https://reader034.vdocument.in/reader034/viewer/2022052410/554f970fb4c905ad218b46bb/html5/thumbnails/4.jpg)
http://www.casualmiracles.com/
FLY
Fly is an ‘Object Space’
Network wide - Object level - Storage and Matching Matching – by Object Templates Object Serialisation – Native to a language or language neutural
Leasing – Information and resources have prescribed lifetimes
![Page 5: Porting Java To Scala](https://reader034.vdocument.in/reader034/viewer/2022052410/554f970fb4c905ad218b46bb/html5/thumbnails/5.jpg)
http://www.casualmiracles.com/
FLY PRIME INTERFACE
public interface FlyPrime {
long write(Object entry, long leaseTime);
Object read(Object template, long waitTime);
Object take(Object template, long waitTime);
}
![Page 6: Porting Java To Scala](https://reader034.vdocument.in/reader034/viewer/2022052410/554f970fb4c905ad218b46bb/html5/thumbnails/6.jpg)
http://www.casualmiracles.com/
DESIGN DIAMONDMinimise Interface
Minimise Uses
Complexity
![Page 7: Porting Java To Scala](https://reader034.vdocument.in/reader034/viewer/2022052410/554f970fb4c905ad218b46bb/html5/thumbnails/7.jpg)
http://www.casualmiracles.com/
FLY SPACE DESIGNMinimal But Complete Interface
Minimal Use of OS interfaces
ThreadingObject Locking
DistributionMatchingExpiring
WriteReadTake
PthreadsSockets
Malloc - Free
![Page 8: Porting Java To Scala](https://reader034.vdocument.in/reader034/viewer/2022052410/554f970fb4c905ad218b46bb/html5/thumbnails/8.jpg)
http://www.casualmiracles.com/
FLY SPACE INTERFACE HIERARCHY
MultiFly writeMany readMany takeMany
FlyPrime writereadtake
NotiFly notifyWrite notifyTake
Fly
![Page 9: Porting Java To Scala](https://reader034.vdocument.in/reader034/viewer/2022052410/554f970fb4c905ad218b46bb/html5/thumbnails/9.jpg)
http://www.casualmiracles.com/
FLY SCALA
Scala Binding
Scala Space Interface
Fly Server
Scala Application Client
Scala Binding
Scala SpaceInterface
Scala Application Client
![Page 10: Porting Java To Scala](https://reader034.vdocument.in/reader034/viewer/2022052410/554f970fb4c905ad218b46bb/html5/thumbnails/10.jpg)
http://www.casualmiracles.com/
FROM JAVA TO SCALA
• Syntactic Conversion
• Idiomatic API
• Idioms Internally
• Actors
• Java and Scala Compared
• What Next?
![Page 11: Porting Java To Scala](https://reader034.vdocument.in/reader034/viewer/2022052410/554f970fb4c905ad218b46bb/html5/thumbnails/11.jpg)
http://www.casualmiracles.com/
SYNTACTIC
public interface NotiFly extends FlyPrime { boolean notifyWrite(Object template, NotifyHandler handler, long leaseTime); boolean notifyTake(Object template, NotifyHandler handler, long leaseTime); }
trait NotiFly extends FlyPrime { def notifyWrite(template: AnyRef, handler: NotifyHandler, leaseTime: Long): Boolean def notifyTake(template:AnyRef, handler:NotifyHandler, leaseTime:Long):Boolean}
![Page 12: Porting Java To Scala](https://reader034.vdocument.in/reader034/viewer/2022052410/554f970fb4c905ad218b46bb/html5/thumbnails/12.jpg)
http://www.casualmiracles.com/
SYNTACTIC
public static void main(String[] args) throws Exception { FileInputStream f = new FileInputStream(new File(args[0])); DataInputStream dis = new DataInputStream(f); StatsDecoder decoder = new StatsDecoder(); long time = dis.readLong(); while ( true ) { int size = dis.readInt(); StatsBean [] beans = decoder.getStatsArray(dis); Stats.writeStats(beans); System.out.println("--------------"); long nextTime = dis.readLong(); Thread.sleep(nextTime-time); time = nextTime; } }
def main(args: Array[String]) {
val f = new FileInputStream(new File(args(0))); val dis = new DataInputStream(f);
val decoder = new StatsDecoder();
var time = dis.readLong(); while (true) { val size = dis.readInt(); val beans = decoder.getStats(dis); StatsPrinter.writeStats(beans); System.out.println("--------------"); val nextTime = dis.readLong(); Thread.sleep(nextTime - time); time = nextTime; } }
![Page 13: Porting Java To Scala](https://reader034.vdocument.in/reader034/viewer/2022052410/554f970fb4c905ad218b46bb/html5/thumbnails/13.jpg)
http://www.casualmiracles.com/
IDIOMS - OPTION
An Option represents an optional value
Two subclasses: Some and None
Java has … null
Experiment with Options in Java later
![Page 14: Porting Java To Scala](https://reader034.vdocument.in/reader034/viewer/2022052410/554f970fb4c905ad218b46bb/html5/thumbnails/14.jpg)
http://www.casualmiracles.com/
IDIOMS - OPTION
trait FlyPrime {
def read[T <: AnyRef](template: T, waitTime: Long): Option[T]}
fly.read(template, 0L) match { case None => { println("No ball in play") serveBall(fly) println("Served Ball - Please start a Pong") } case Some(gameBall) => { println("Received ball - game on!") returnBall(fly, gameBall) }}
pattern matching - scala can extract values from the matching pattern - Some(ball)no types
![Page 15: Porting Java To Scala](https://reader034.vdocument.in/reader034/viewer/2022052410/554f970fb4c905ad218b46bb/html5/thumbnails/15.jpg)
http://www.casualmiracles.com/
IDIOMS - OPTION
trait FlyPrime {
def read[T <: AnyRef](template: T, waitTime: Long): Option[T]}
fly.read(template, 0L) match { case None => // do nothing case Some(gameBall) => doSomething(gameBall)}
fly.read(template, 0L).map((x:T) => doSomething(x))
fly.read(template, 0L).map(doSomething(_))
do nothing for none - verbose to use pattern matching(x:T) => doSomething(x) is a first class function
![Page 16: Porting Java To Scala](https://reader034.vdocument.in/reader034/viewer/2022052410/554f970fb4c905ad218b46bb/html5/thumbnails/16.jpg)
http://www.casualmiracles.com/
ASIDE
Options can be implemented in other languages
Clumsy in Java but still useful
An experiment:
Problems exposed where null was not expected
Clarify business logic and behaviour
![Page 17: Porting Java To Scala](https://reader034.vdocument.in/reader034/viewer/2022052410/554f970fb4c905ad218b46bb/html5/thumbnails/17.jpg)
http://www.casualmiracles.com/
IDIOMS - RETURN VALUES
int iterations = 10000;if (args.length > 0) iterations = Integer.parseInt(args[0]);
val iterations = if (args.length > 0) args(0).toInt else 10000
def urlFor(path: String) = try { new URL(path) } catch { case e: MalformedURLException => new URL("http://www.scala-lang.org") }
pattern matching for exceptionsexceptions are runtime
![Page 18: Porting Java To Scala](https://reader034.vdocument.in/reader034/viewer/2022052410/554f970fb4c905ad218b46bb/html5/thumbnails/18.jpg)
http://www.casualmiracles.com/
IDIOMS - FILTERING
public Collection<FlyServerRep> getMatchingReps(String [] tags) { Collection matched = new ArrayList<FlyServerRep>(); for (FlyServerRep rep : reps.values()) { if (rep.tagsMatch(tags)) { matched.add(rep); } } return matched; }
def getMatchingReps(tags:Array[String]):Collection[FlyServerRep] = reps.values.filter((rep:FlyServerRep) => rep.tagsMatch(tags)).toList
def getMatchingReps(tags:Array[String]):Collection[FlyServerRep] = reps.values.filter(_.tagsMatch(tags)).toList
filter items from a collection
![Page 19: Porting Java To Scala](https://reader034.vdocument.in/reader034/viewer/2022052410/554f970fb4c905ad218b46bb/html5/thumbnails/19.jpg)
http://www.casualmiracles.com/
IDIOMS - COMPREHENSIONS
public StatsBean[] getStatsArray(DataInputStream dis) throws IOException { long statsCount = dis.readLong(); StatsBean [] stats = new StatsBean[(int)statsCount]; for (int i = 0; i < statsCount; i++) { stats[i] = StatsBean.makeBeanFromStream(dis); } return stats;}
def getStats(dis: DataInputStream): Seq[StatsBean] = for (i <- 0 until dis.readLong().toInt) yield StatsBean.makeBeanFromStream(dis)
Create an array of itemsfor comprehension - iterate over something collecting results of the expression after yield
![Page 20: Porting Java To Scala](https://reader034.vdocument.in/reader034/viewer/2022052410/554f970fb4c905ad218b46bb/html5/thumbnails/20.jpg)
http://www.casualmiracles.com/
FOR COMPREHENSION
Syntax: for ( seq ) yield e
Where seq is a sequence of generators, definitions and filters
e evaluated for each binding of generators and definitions
Return a sequence of evaluated values
generator— roughly speaking, an expression that pulls an item from a collectioneasier to show an example...
![Page 21: Porting Java To Scala](https://reader034.vdocument.in/reader034/viewer/2022052410/554f970fb4c905ad218b46bb/html5/thumbnails/21.jpg)
http://www.casualmiracles.com/
FOR COMPREHENSION
val names = for {
p <- persons // a generator
n = p.name // a definition
if (n startsWith "To") // a filter
} yield n
p bound to each item in persons
![Page 22: Porting Java To Scala](https://reader034.vdocument.in/reader034/viewer/2022052410/554f970fb4c905ad218b46bb/html5/thumbnails/22.jpg)
http://www.casualmiracles.com/
IDIOMS - FOLD /*** @return the lease of the last entry written*/public long writeMany(Collection entries, long lease) { long lastLease = 0; for (Object entry : entries) { lastLease = codec.write( entry, lease ); } return lastLease;}
def writeMany(entries: Collection[AnyRef], lease: Long): Long = (0L /: entries){(previousLease, nextEntry) => codec.write(nextEntry, lease)}
method writes entries to the space and returns the lease of the last item writtenfunction takes two parameters, ignores previousLease, returns the result of codec.writegood use of fold?
![Page 23: Porting Java To Scala](https://reader034.vdocument.in/reader034/viewer/2022052410/554f970fb4c905ad218b46bb/html5/thumbnails/23.jpg)
http://www.casualmiracles.com/
IDIOMS - ACCESSORS public class FlyServerRep { private String [] flyTags; private InetAddress flyAddr; FlyServerRep(InetAddress addr, String[] tags) { flyAddr = addr; flyTags = tags; } public String[] getFlyTags() { return flyTags; }
public void setFlyTags(String[] flyTags) { this.flyTags = flyTags; }
public InetAddress getFlyAddr() { return flyAddr; }
public void setFlyAddr(InetAddress flyAddr) { this.flyAddr = flyAddr; }}
class FlyServerRep(var flyAddr:InetAddress, var flyTags:Array[String])
var on constructor parameters, scala generates accessor methods: x and x_
![Page 24: Porting Java To Scala](https://reader034.vdocument.in/reader034/viewer/2022052410/554f970fb4c905ad218b46bb/html5/thumbnails/24.jpg)
http://www.casualmiracles.com/
IDIOMS - FUNCTIONS public Object read(Object template, long timeout) { Object ret = codec.read(template, 0); .... while(...) ret = codec.read(template, 0);
def read[T <: AnyRef](template: T, timeout: Long): Option[T] = retrieve(template, timeout, codec.read)def take[T <: AnyRef](template: T, timeout: Long): Option[T] = retrieve(template, timeout, codec.take)
private def retrieve[T](template: T, timeout: Long, m: (T, Long) => Option[T]): Option[T] = { var ret = m(template, 0L) .... while(...) ret = m(template, 0)
public Object take(Object template, long timeout) { Object ret = codec.take(template, 0); .... while(...) ret = codec.take(template, 0);
![Page 25: Porting Java To Scala](https://reader034.vdocument.in/reader034/viewer/2022052410/554f970fb4c905ad218b46bb/html5/thumbnails/25.jpg)
http://www.casualmiracles.com/
CONTROL ABSTRACTIONSystem.out.println("Processing " + iterations + " writes and reads");long start = System.currentTimeMillis();for (int i = 0; i < iterations; i++) { space.write(object, 1000); space.read(template, 0L);}long end = System.currentTimeMillis();float timeInSeconds = (float) (end - start) / 1000.0f;System.out.println("Which took " + timeInSeconds + " seconds\n");
![Page 26: Porting Java To Scala](https://reader034.vdocument.in/reader034/viewer/2022052410/554f970fb4c905ad218b46bb/html5/thumbnails/26.jpg)
http://www.casualmiracles.com/
CONTROL ABSTRACTIONTime("Processing " + iterations + " writes and takes", iterations) { space.write(obj, 1000) space.take(template, 0L)}
object Time { def apply(name: String, iterations: Int)(block: => Unit): Unit = { println(name) val start = System.currentTimeMillis()
for (i <- 0 until iterations) block
val end = System.currentTimeMillis() val timeInSeconds = (end - start) / 1000.0F println("Completed in " + timeInSeconds + " seconds\n") }}
apply methods have special meaning - invoked using a method-less expressioneg Time (... is the same as Time.apply(...
![Page 27: Porting Java To Scala](https://reader034.vdocument.in/reader034/viewer/2022052410/554f970fb4c905ad218b46bb/html5/thumbnails/27.jpg)
http://www.casualmiracles.com/
CONTROL ABSTRACTION
trait NotiFly extends FlyPrime { def notifyWrite(template: AnyRef, leaseTime: Long)(block: => Unit): Boolean}
fly.notifyWrite(template, LEASE){ println("Block Template matched!")}
![Page 28: Porting Java To Scala](https://reader034.vdocument.in/reader034/viewer/2022052410/554f970fb4c905ad218b46bb/html5/thumbnails/28.jpg)
http://www.casualmiracles.com/
ACTORS
Scala’s primary concurrency construct
Concurrent processes communicating by exchanging messages
Scala Actor implementation is a library - several of them
![Page 29: Porting Java To Scala](https://reader034.vdocument.in/reader034/viewer/2022052410/554f970fb4c905ad218b46bb/html5/thumbnails/29.jpg)
http://www.casualmiracles.com/
ACTORS
trait NotiFly extends FlyPrime { def notifyWrite(template: AnyRef, leaseTime: Long, actor: Actor): Boolean}
import scala.actors.Actor._val myActor = actor { // factory method taking a block loop { // we want the actor to keep processing messages react { // handle messages case FlyPrime.ACTOR_MESSAGE => println("Actor received a message!") } } }
fly.notifyWrite(template, LEASE, myActor)
![Page 30: Porting Java To Scala](https://reader034.vdocument.in/reader034/viewer/2022052410/554f970fb4c905ad218b46bb/html5/thumbnails/30.jpg)
http://www.casualmiracles.com/
JAVA TO SCALA COMPARED Java has 1556 LoC, Scala has 934 LoC => 60%
Core code is about half the size
Why?
Most algorithms can be characterised as Searching, Sorting, Filtering, Mapping, Combining, Counting (Peter Norvig)
Scala and functional languages provide good abstractions for these
Java is 2% faster
Need more comprehensive tests to find out why
![Page 31: Porting Java To Scala](https://reader034.vdocument.in/reader034/viewer/2022052410/554f970fb4c905ad218b46bb/html5/thumbnails/31.jpg)
http://www.casualmiracles.com/
WHAT NEXT? Scala 2.8
Port from 2.7.7 complete
Available for 2.8 soon
Implement the library from scratch?
Design of existing library is the same as the Java library
Current version made improvements in the small
Perhaps a more functional approach would be better?
![Page 32: Porting Java To Scala](https://reader034.vdocument.in/reader034/viewer/2022052410/554f970fb4c905ad218b46bb/html5/thumbnails/32.jpg)
http://www.casualmiracles.com/
FROM JAVA TO SCALA
><----
--------->
<---->
2/3 lines of codecould be better