scala in the wild
TRANSCRIPT
Scala in the WildDaniel Spiewak
Vanity Slide
• Software Developer at Novell
• Working on a next-gen communications system called “Pulse”
• Author of Scala for Java Refugees
• ...and a fair bit more
• An unhealthy fascination with languages
Brief Overview of Pulse
• Next-Gen communications platform
• Implemented as a web application
• AJAX
• Comet
• Focus on security and enterprise management
Architecture
Webapp (Lift)
Search Service (SOLR)
Notification Service
HBase
RabbitMQ
MySQL+
WFP Service
Messaging Service
Nifty Tricks
• Messages are chunks of XML
<message id="42"> <line/>Playing with Pulse (and trying to avoid accidentally poluting any of Andy's demos).
<message id="43"> <line/>We can reply quite easily. </message></message>
Nifty Tricks
• Messages are chunks of XML
• Extend Elem
• Custom NoBindingFactoryAdapter
• Use #load(String)
Nifty Tricks
• Messages are chunks of XML
• All frontend services use Cake Pattern
• Very extensive use of actors
Challenges
• Actors require a recovery mechanism
• Java / Scala interop is a little clumsy
• Collections conversion (java-utils)
import scala.collection.jcl.Conversions._ def foo(bar: java.util.List[String]) = { val xs: Seq[String] = bar bar.add("baz") xs foreach println // does it contain "baz"?} def foo(bar: List[String]) = { val back = new java.util.ArrayList[String] bar foreach back.add back}
import org.scala_tools.javautils.Implicits._
def foo(bar: java.util.List[String]) = { val xs = bar.asScala bar.add("baz") xs foreach println}
// returns java.util.List[String], and in O(1) too!def foo(bar: List[String]) = bar.asJava
Challenges
• Actors require a recovery mechanism
• Java / Scala interop is a little clumsy
• Collections conversion (java-utils)
• Spring doesn’t like mixins
• Tools are primitive (at best)
• Scala devs are in short supply
Java Refugees
• Tendency to write Java in Scala
class Person(fn :String, ln :String) { private var theFirstName :String = fn; private var theLastName :String = ln; def getFirstName() :String = { return theFirstName; } def setFirstName(fn :String) :Unit = { theFirstName = fn; } // ... override def equals(obj: Any) :Boolean = { if (obj.isInstanceOf[Person]) { var p :Person = obj.asInstanceOf[Person]; return p.getFirstName() == theFirstName && p.getLastName() == theLastName; } return false; }}
class Person(var firstName: String, var lastName: String) { override def equals(a: Any) = a match { case that: Person => { this.firstName == that.firstName && this.lastName == that.lastName } case _ => false }}
Java Refugees
• Tendency to write Java in Scala
• Failure to exploit advanced features
• Nested imports
• Point-Free / Currying
• Monads
def foo(bar: Bar) = { var result: Baz = null Box.!!(bar).foreach(person => Box.!!(person.name).foreach(name => Box.!!(name.find("blah")).foreach(result = _))) Box !! result}
def foo(bar: Bar) = { for { person <- Box !! bar name <- Box !! person.name result <- Box !! (name find "blah") } yield result}
Java Refugees
• Tendency to write Java in Scala
• Failure to exploit advanced features
• Nested imports
• Point-Free / Currying
• Monads
• Higher-Kinds only raise confusion
• Arbitrary file organization
Solution: Conventions!
http://davetron5000.github.com/scala-style/
Scala Style• Inspirations
• Java
• Standard ML
• Haskell
• C#
• OCaml
• Ruby
• Python
Scala Style
• Leverage type inference!
val s: String = "blah" // wrongval s = "blah" // right
Scala Style
• Leverage type inference!
• Higher-Order functions// wrongdef foldLeft[A](init: A, f: (A, B) => A) = ...// rightdef foldLeft[A](init: A)(f: (A, B) => A) = ...
foldLeft(0) { (a, b) => ... }
Scala Style
• Leverage type inference!
• Higher-Order functions
• Function valuesfoo (x) => x + 1 // wrongfoo (x) => { x + 1 } // wrong
foo { _ + 1 } // rightfoo { x => x + 1 } // right
Scala Style
• Leverage type inference!
• Higher-Order functions
• Function values
• Correct use of implicits
• Pimp-my-library
• Correcting inheritance (typeclasses)
Scala Style
• ...
• Function values
• Rules for correct use of implicits
• Arity-0 methodsprintln // wrongprintln() // right
xs.length() // wrongxs.length // right
Scala Style
• Leverage type inference!
• Higher-Order functions
• Function values
• Rules for correct use of implicits
• Arity-0 methods
• File organization
Conclusion(s)
• Yes, Scala is ready for the enterprise!
• ...but there’s definitely room to improve
• Process and conventions are critical
• Community is developing standards. Participate!
Thank You