Scaling API-first – The story of a global engineering organization
Scala @ TomTom
1. Scala @ TomTom Eric Bowman eric.bowman@tomtom.com 26 May 2010
2. What’s He Building In There? Not just PNDs Traffic Services Location Services Address & Local Search Tons of Data -> Tons of Analysis Deep Commitment to Server-Side Java 2
25. Scala Is... An escaped research language from EPFL targeting JVM and CLR Object-oriented and functional Statically typed Lisp, ML, Haskell, Erlang, etc. DSL-friendly 12
27. Functional Programming? Functions as first class objects Immutability Closures Binding free variables to enclosing lexical scope Higher-order Functions functions as input and/or output A different set of idioms... 14
28. Keep Back for (int i = 1; i <= 256; i++) { if (array[i-1] == ... 15
31. Java Idioms ++C++ No more 0xDEADBEEF Leads to lots of loops and copies, if you’re doing it right Hard programs get complex doing common things Nested loops begin to look Harmful... 18
33. For Comprehensions for(inti=0; i<100; i++) { ... } for (i <- 0 until 100) { ... /* do something with i */ } (0.until(100)).foreach(i => /* something with i */) 20
35. The Easy Ones for (i <- 1 to 6) yield i * 2 (1 to 6).map(_ * 2) (2,4,6,8,10,12) for (i <- 1 to 6 if i % 2 == 0) yield i (1 to 6).filter(_ % 2 == 0) (2,4,6) for (i <- 1 to 6) { println(i + “ “) } (1 to 6).foreach { i => print(i + “ “) } 1 2 3 4 5 6 22
36. A Harder One... List<Integer> array = new ArrayList<Integer>(); for (i = 1; i <= 3; i++) { for (j = i; j <= 3; j++) { array.add(j); } } System.out.println(array); [1, 2, 3, 2, 3, 3] for (i <- 1 to 3; j <- i to 3) yield j (1, 2, 3, 2, 3, 3) (1 to 3).flatMap(i => (i to 3).map(j => j)) 23
37. flatMap Subtle thing... “Applies the given function f to each element, then concatenates the results” Turns a list of lists into a list List(List(1,2,3), List(4,5,6)).flatMap(x => x) List(1, 2, 3, 4, 5, 6) List(“tom”, “tom”).flatMap(_.capitalize).mkString TomTom “Special sauce” for nested looping constructs (Equivalent to Haskell’s monadic “bind”) 24
38. IteratorIterator package org.hyperic.sigar.util; public static class IteratorIteratorimplements java.util.Iterator { private java.util.ArrayListiterators; public IteratorIterator() {} public void add(java.util.Iteratoriterator) {} public booleanhasNext() {} public java.lang.Object next() {} public void remove() {} } 25
39. flatMapflatMap def foo(arg: Iterable[Int]) { ... Do something with arg } val some: Iterable[Int] = getSomeIterable foo(some) val more: Iterable[Int] = getMore foo(List(some, more).flatMap(x => x)) 26
45. Yeah yeahyeah but “Perl Whitespace Law” “Each line of perl should be surrounded by whitespace equivalent to what it would take to achieve the same functionality in a normal programming language.” -- Don Hopkins If it compiles, it nearly works. Really. Visual Plane-Oriented Programming I ♥ Idioms “But in Java, each little part is so very simple...” 32
48. “Weak developers will move heaven and earth to do the wrong thing. You can’t limit the damage they do by locking up the sharp tools. They’ll just swing the blunt tools harder.” – Glenn Vandenburg 35
50. How To Sneak It In Start with Testing ScalaCheckIS AWESOME. Specs, ScalaTest testing DSLs Start with something low risk Ok, well, we didn’t do that Prepare for steep learning curve ...followed by a productivity hockey stick 37
51. Another Example 8000 lines of broken Java -> 400 lines of broken Scala -> hyp.take(1).flatMap(_.dropDistricts) match { case Nil => hyp case head => { hyp.tail.foldLeft(head) { case (run: List[Hypothesis], h: Hypothesis) => { run.flatMap(_.merge(h)) match { case Nil => run case newRun => newRun.removeDuplicates } } } } } *Includes suggested improvements by Martin Odersky, I hope 38
52. Testing Functional architect wrote a bunch of test cases, like: Requirement R.17: D1 -> N1, L1 -> N1, N1, D2 -> L2, L3, N3, D3 should cluster as (L1,N1,D1), (L2,D2), (L3), (N3), (D3) Vim-macro’d into: it should “satisfy R.17” in { cluster(D1 -> N1,L1 -> N1,N1,D2 -> L2,L3,N3,D3) should equal { groups(group(L1,N1,D1),group(L2,D2),group(L3),group(N3), group(D3))) } 39