T LIN KEDIN LIVIN G SO C IAL Q U O RA REM EM BER TH E M ILK SEESM IC STAC KM O B TW ITTER TU M BLR VM W ARE YAM M ER N O VEL AO L BO X E-H ARM O N Y http://www.quora.com/Startups/What-startups-or-tech-companies-are-using-Scala
support for map, flatmap, tabulate, filter, foreach... Traits, classes, case classes, object... Attach behaviors at runtime. new Foo with Other Flexible syntax, create constructs, infix support, everything is a value val test = if(...) val collection = for(...) Emphasis on immutable data structures. Transformations and copies vs state Built in support for this high concurrency pattern IMMUTABILITY EMPHASIS FUNCTIONAL OOP ACTORS MIXINS IDIOMATIC
need synchronization JAVA List<Integer> even = new ArrayList<Integer>(); for (String num : numbersAsStrings) { int parsedInt = Integer.parseInt(num); if (parsedInt % 2 == 0) { ints.add(parsedInt); } } In Scala we transform values into new values SCALA val ints = for (num <- numbersAsStrings; if num.toInt % 2 == 0) yield num.toInt No need to synchronize in structures which state is never modified
= 1 myInt: Int = 1 scala> def myFunction = "I don't need a return" myFunction: String scala> val result = for (n <- 0 to 10) yield n result: scala.collection.immutable.IndexedSeq[Int] = Vector(0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10) scala> val ifAreValues2 = if (true) "test" ifAreValues2: Any = test scala> val ifAreValues3 = if (true) "test" else "test2" ifAreValues3: String = test Functional style encourages to pipe the results of functions and operations Vs Imperative style Iterator.continually(Option(queue.poll(1, TimeUnit.SECONDS))).takeWhile(_ => running) foreach { msg => write(msg) }
messaging system /** invoke your army **/ val emailServiceActor = Akka.system.actorOf( Props[EmailServiceActor].withRouter( SmallestMailboxRouter(nrOfInstances = 50) ), name = "emailService" ) /** send him to war **/ emailServiceActor ! emailMessage /** this is the guy overseeing everything in the pentagon **/ class EmailServiceActor extends Actor{ override val supervisorStrategy = OneForOneStrategy(maxNrOfRetries = 10) { case emailException: EmailException => Restart case unknownCase: Any => Stop } def receive = { case message: Any => context.actorOf(Props[EmailServiceWorker]) ! message } } /** And this one is the one in the field **/ class EmailServiceWorker extends Actor{ /** And this one is the one in the field **/ private var emailMessage: Option[EmailMessage] = None def receive = { case Some(email): EmailMessage => { email.deliveryAttempts = email.deliveryAttempts + 1 email sendEmailSync() } case unexpectedMessage: Any => throw new Exception("can't handle %s" format(unexpectedMessage)) } override def preRestart(reason: Throwable, message: Option[Any]) { context.system.scheduler.scheduleOnce(emailMessage.get.retryOn, self, emailMessage.get) } }
= println("I'm swimming")} class Fish extends Swimmer ... trait Walker { def walk = println("I'm walking")} val mudSkipper = new Fish() with Walker mudSkipper.walk()
that you usually solve by looping over and manually creating intermediate containers. Transformed results stay immutable and thread safe. No need to reinvent the wheel. Code becomes readable and idiomatic "betabeers" groupBy identity mapValues (_.size)