Scala Intro
Upcoming SlideShare
Loading in...5
×
 

Scala Intro

on

  • 3,320 views

Scala Intro training @ Lohika, Odessa, UA.

Scala Intro training @ Lohika, Odessa, UA.

This is a basic Scala Programming Language overview intended to evangelize the language among any-language programmers.

Statistics

Views

Total Views
3,320
Views on SlideShare
3,100
Embed Views
220

Actions

Likes
13
Downloads
84
Comments
0

7 Embeds 220

http://blog.mrmig.info 169
http://www.fse.guru 34
http://blog.fse.guru 7
http://www.linkedin.com 4
https://twitter.com 2
http://plus.url.google.com 2
http://scalatroll.blogspot.com 2
More...

Accessibility

Categories

Upload Details

Uploaded via as Microsoft PowerPoint

Usage Rights

© All Rights Reserved

Report content

Flagged as inappropriate Flag as inappropriate
Flag as inappropriate

Select your reason for flagging this presentation as inappropriate.

Cancel
  • Full Name Full Name Comment goes here.
    Are you sure you want to
    Your message goes here
    Processing…
Post Comment
Edit your comment
  • Step 1 – 10 mins1. Scala history2. Complexity3. Use cases4. Who is using5. Use Java libs6. Multiparadigm language7. Prefer functional style8. Expressiveness9. Strongly statical typed10. Hello World
  • Design started in 2001First release – 2003Author - Martin Odersky1000 downloads/month on official site today
  • NB: the actions uponBigInt seems like actions over the built-in language features (types)* Scalable language – can be “scaled” by developer’s needs.* It suits great to write DSLs.
  • Step 2 – 15 mins1. What is immutability2. Why is it matter3. Difference between val / var (Example showing that we cannot re-asinval)4. Collections are immutable5. Mutable approaches allowed but not prefered6. Everything returns data (example with Java vsScala if statement)
  • ----- Meeting Notes (16.10.13 10:57) -----Add val and var examples
  • The second main idea of functional programming is that the operations of a program should map input values to output values rather than change data in place. Another way of stating this second idea of functional programming is that methods should not have any side effects.
  • ----- Meeting Notes (16.10.13 14:02) -----Add additional pointsAdd note to slide to see later
  • Promotes declarative functional style vs imperative style
  • Immutability => bad performance (memory)Objects everywhere => bad performance NOPE!Scalavsoptimezed C++ = (x2.5 - x3.6)Java vs opt C++ = (x3.7 – x5.8)
  • Step 3 – 25 mins1. Class = Java Class. Nothing special. Example. How constructor works.2. Object = singleton pattern (Example)3. Case class = class with convenient extensions (POJO in other words) (Example)4. Abstract class - do define structure5. Trait - to define behaviour. Stack modifications.6. Diamond problem solved
  • ----- Meeting Notes (16.10.13 10:57) -----Fiz >> to "
  • Companion object pattern ?
  • What does “case” mean?Getters/setters + constructor + apply/unapply (pattern matching) + companion object
  • What does “case” mean?Getters/setters + constructor + apply/unapply (pattern matching) + companion object
  • ----- Meeting Notes (16.10.13 11:24) -----Add logger exampleAdd abstract class and trait exampleAdd #5 - Diamond problem solved slide
  • Step 4 – 10 minutes1. Scala basic types are objects (no primitives) 2. Scala implement own types3. Type list
  • + Literals+ Reside in scala package+ Imports automatic
  • Step 5 – 20mins1. Any is a top of hierarchy2. Basic types extends AnyVal3. Others extends AnyRef4. Any class extends Null implicitly5. Any class extends Nothing. Nothing is used in methods which returnds nothing (throw exception of terminate application)6. Unit = void----- Meeting Notes (16.10.13 11:24) -----Add User = null exampleadd Nothing example with throwLocalozedException
  • defthrowLocalizedException(key: String): Nothing = { throw LocalizedException(resolveMessage(key))}
  • Step 6 – 25 mins----- Meeting Notes (16.10.13 14:02) -----Add first class function example and slides
  • Note that it is "idealogically"Add right examples
  • ----- Meeting Notes (16.10.13 14:02) -----Add additional pointsAdd note to slide to see later
  • Step 7 – 15 min1. What is type inference2. Example with assigning variable3. Example with method return type4. Method parameters require types!Yes, it is logical. No, compiler cannot read your mind.
  • ----- Meeting Notes (16.10.13 14:02) -----Remove class wrapper context
  • ----- Meeting Notes (16.10.13 14:02) -----remove b:String - StringAdd Alex's examplesAdd example with if then else with
  • Lambda syntax
  • Step 8 – 30 minReplace with:2) Closure (definition, difference from lambda)3) Posible problems4) Closures like anonymous class in Java5) Full example
  • Step 9 – 60 min1. 2 Different types of collections. Mutable / Immutable. Show package names.2. Class Hierarchy (http://www.programmera.net/scala/img/seq_tree.png)3. 3 main traits (Map, Set, List) examples. (Immutable)Live codding. Show only main methods like map, flatMap, filter, foreach, reduce.Others will be shown in a table with a short description
  • Step 10 – 15 minsSimple examples with fors, filters, embededfors.Live coding?
  • Step 10 – 15 minsSimple examples with fors, filters, embededfors.Live coding?
  • Step 10 – 15 minsSimple examples with fors, filters, embededfors.Live coding?
  • Step 10 – 15 minsSimple examples with fors, filters, embededfors.Live coding?
  • Step 10 – 15 minsSimple examples with fors, filters, embededfors.Live coding?
  • Step 10 – 15 minsSimple examples with fors, filters, embededfors.Live coding?
  • Step 10 – 15 minsSimple examples with fors, filters, embededfors.Live coding?
  • ----- Meeting Notes (16.10.13 14:02) -----Add embedded for and filtersAdd for definitions
  • Step 12 – 30 mins1. Switch on steroids2. Exceptions example3. Case classes with pattern mathing + parameters extraction
  • Step 13 – 20 minsWhat are implicits2. Implicit variables3. Implicit class structure extension (pimp my library)vals, methods, prototyping
  • Step 14 – 10 mins+Tail recursionlazy evaluationlazy initializationOptionsMonadse.t.c in the end
  • Backticks to override reserved identifiers

Scala Intro Scala Intro Presentation Transcript

  • Scala Intro val you = new Developer[Any] with ScalaKnowledge
  • Is Scala really hard? Can I start using it without going mad? Why zombies?
  • Scala History . Scala 2003 AD
  • • • • • • Pizza GJ generics in Java Funnel Scala
  • Scala is a pure object-oriented language Scala is also a functional language Strongly statically typed Runs on JVM, compiles to bytecode
  • Scala – scalable language def factorial(x: BigInt): BigInt = if (x == 0) 1 else x * factorial(x - 1)
  • In contrast with C++, the more you study Scala, the easier it gets. Unknown Scala community member
  • Scala in Production http://www.scala-lang.org/old/node/1658
  • Hello … object HelloZombie extends App { println("Hello, " + "Zombie!") }
  • Another Hello object HelloZombie { def main(args: Array[String]) { println("Hello, " + "Zombie!") } }
  • You do not need CS degree to code in Scala Application Programmers: A1 – A3 levels Library Designers: L1 – L3 levels «One can program very productively in Scala on level A1, which one should be able to pick up in a day or so, coming from Java. Mastering A2 will doubtlessly increase programmer productivity. A3 is for expert programmers with more specialized tasks, not everyone needs to get to that level.» http://www.scala-lang.org/old/node/8610.html
  • Scala functional basics
  • #1 - Mutability is evil #2 – Everyhting returns data #3 – Functions are first-class citizens
  • Mutability is evil • Mutable objects are complicated to think about • Defensive copies • Need to be synchronized in multithreaded env • Unobvious side effects
  • Mutability is evil val salary = "2000$" salary = "2500$" // does not compile var salary = "2000$” salary = "2500$” // compiles
  • Everything returns data val result = if (true) value1 else value2 val result = for (i <- 1 to 10) yield i def getRandom() = { Math.random() }
  • Functions are first-class citizens Assign function definitions to variables val doubled = (x:Int) => x * 2
  • in Scala a function value is an object! Scala => pure OOP & full-blown functional language
  • Sooo many objects around Baaaad performance, yeah?
  • http://readwrite.com/2011/06/06/cpp-go-java-scala-performance-benchmark
  • Scala OOP basics
  • #1 - Class #2 - Object = build-in singleton pattern #3 – Case class #4 – Abstract class vs Trait #5 – Multiple inheritance WAT? Diamond problem solved!
  • Class Class is similar to any other languages’ class notion class MyZombie { private val index: Int = 0 val name: String = "Zombie0" }
  • Class + Constructor class MyZombie(index: Int, val name: String) { println("me likes brainz!") }
  • Object Objects are singletons object LoneZombie { def growl = println("me sooo sad") }
  • Companion Object class CrawlerZombie(name: String) { def crawl() = println("crawling...") } object CrawlerZombie { def apply(name: String) = { println(name + " is here!") new CrawlerZombie(name) } } val zombie = CrawlerZombie("Mig") zombie.crawl()
  • Case Class Case class = class + “sugar” + compiler hint case class Zombie(index: Int, name : String)
  • Case Class Sugar 1. Properties 2. Pattern Matching 3. Companion Object
  • Abstract class vs Trait Abstract class defines structure Trait defines behaviour
  • Abstract Class abstract class Undead(name: String) { def eat() = { println("Om nom nom") digest() } def digest() } class Zombie(name: String) extends Undead(name) { def digest() = { println("grab brainz") } }
  • Trait abstract class Undead(name: String) { def eat() = { println("Om nom nom") digest() } def digest() } trait Growling{ def growl(msg: String) = println(msg) def scream(msg: String) = println(msg + " !!!") } class Zombie(name: String) extends Undead(name) with Growling { def digest() = { growl("grab brainz") } }
  • Scala Basic Types
  • #1 - Scala basic types are objects #2 – Scala implement it’s own types, wraps and extends some Java classes and types #3 Scala operators are method calls
  • Value type Range Byte 8-bit signed two's complement integer (27 to 27 - 1, inclusive) Short 16-bit signed two's complement integer (-215 to 215 - 1, inclusive) Int 32-bit signed two's complement integer (-231 to 231 - 1, inclusive) Long 64-bit signed two's complement integer (-263 to 263 - 1, inclusive) Char 16-bit unsigned Unicode character (0 to 216 - 1, inclusive) String a sequence of Chars Float 32-bit IEEE 754 single-precision float Double 64-bit IEEE 754 double-precision float Boolean true or false
  • Operators are methods Operators uses infix notation val sum = 1 + 2 // Scala invokes (1).+(2)
  • Class Hierarchy
  • Null ? var zombie: Zombie = null zombie = new Zombie("Alex")
  • Nothing? def throwLocalizedException(key: String): Nothing = { throw LocalizedException(resolveMessage(key)) }
  • Functions vs methods
  • Functions and methods are not the same!
  • ©
  • Functions No side effects Evaluates only body and parameters Compiles to FunctionN Defined mostly in Objects
  • Functions object KillerModule { def kill = (z: Zombie) => println("Killing " + z.name) }
  • Methods Defined in classes Works with class scope
  • Methods class ZombieTortureMachine(z: Zombie) { def kill() = println("Killing " + z.name) def starve() = println("Starving " + z.name) }
  • Functions are first-class citizens Assign function definitions to variables val doubled = (x:Int) => x * 2
  • Functions are first-class citizens Pass function as a parameter def traverseTree (callback: (Element) => Unit) { val element = ??? //Getting tree element callback(element) }
  • Functions are first-class citizens Return function as a result value def prepareCalculator(x: Int, y: Int): () => Int = { println("calculating...") () => x + y }
  • Type Inference
  • You can omit types in declarations! The compiler will infer them for you. Less typing -> less reading -> happier developers 
  • Type inference with variables private val index = 0 val name = "Zombie0" private val index: Int = 0 val name: String = "Zombie0"
  • Type inference with functions Scala compiler can not read thoughts  def func (a: Int, b: String) = { a + b } // compiles def func1 (a, b) = { a + b } // does not compile
  • Type inference def getZombies(severity: Int) = { if (severity > 10) { List() } else { List(Zombie("Mig"), Zombie("Alex")) } } // inferred type = List[Zombie]
  • Lambda Syntax val doubler = (n: Int) => n * 2 val yadobler = { n: Int => n * 2 }
  • Closures
  • Closure is special kind of a function Closure encloses the local lexical context inside the function body Closures can be implemented using Anonymous classes in Java (yuck!)
  • Simple Closure val multiplier = 2 val doubler = (n: Int) => n * multiplier
  • Closure vs Function Pure function calculates its result solely in terms of its arguments! Closure can use the outer lexical context for it computations. One may say that it stores “references” to the outer values.
  • Collections
  • Sugar : Map Initialization Java: Map<String, Integer> mappings = new HashMap<String, Integer>() {{ put("One", 1); put("Two", 2); put("Three", 3); }}; Scala: val mappings = Map( "one" -> 1, "two" -> 2, "three" -> 3 )
  • Sugar : Filtering Java: List<Integer> numbers = new ArrayList<Integer>(){{ add(1); add(2); add(-55); add(-33); add(122); }}; List<Integer> negativeNumbers = new ArrayList<Integer>(); for (Integer number : numbers) { if (number < 0) { negativeNumbers.add(number); } } Scala: val numbers = List(1, 2, -55, -33, 122) val negativeNumbers = numbers.filter(_ < 0)
  • Sugar : Classification Java: List<Integer> numbers = new ArrayList<Integer>(){{ add(1); add(2); add(-55); add(-33); add(122); }}; List<Integer> negativeNumbers = new ArrayList<Integer>(); List<Integer> positiveNumbers = new ArrayList<Integer>(); for (Integer number : numbers) { if (number < 0) { negativeNumbers.add(number); } else { positiveNumbers.add(number); } } Scala: val numbers = List(1, 2, -55, -33, 122) val (positiveNumbers, negativeNumbers) = numbers.span(_ > 0)
  • Stuff : Tuples • Tuples can be viewed as simple immutable collections. • Tuple can contain up to 22 elements of different types. • Very useful when you need to return a complex value from the expression
  • Stuff : Tuples val pair = (22, "zombies") val pair = (22 -> "zombies") // the type is Tuple2[Int, String] println(pair._1) println(pair._2)
  • Mutable vs Immutable Prefer immutable collections by default. Period. Google for details. Scala uses immutable collections by default val map = Map("one" -> 1) //results in scala.collection.immutable.Map[String,Int]
  • Collections practices Map, Set and List are mostly used collections in Scala Use traits’ companion object calls to create collections when you do not need specific implementation: Map("one" -> 1) // good HashMap("one" -> 1) // not so good new HashMap("one" -> 1) // won't compile :)
  • Collections API example #1 case class User(name: String, password: String) val users = List("admin:nimda", "user1:asddsa", "root:qwerty") val mappedUsers = users.map { user => val splitted = user.split(":") User(splitted(0), splitted(1)) } // List[User] = List(User(admin,nimda), User(user1,asddsa), User(root,qwerty))
  • Collections API example #2 val names = List( "Alex,Viktor,Eugeny", "Dmitry,Yegor, Sergey", "Michael,Sergey") val splitted = names.flatMap(_.split(",").toList).distinct // List(Alex, Viktor, Eugeny, Dmitry, Yegor, Michael, Sergey)
  • Loops & For comprehension
  • Loops & For comprehension • Scala has a while loop • Scala has a do-while loop • They are not expressions (the return type is Unit)
  • Loops & For comprehension Because the while loop results in no value, it is often left out of pure functional languages. Such languages have expressions, not loops. Scala includes the while loop nonetheless, because sometimes an imperative solution can be more readable, especially to programmers with a predominantly imperative background.
  • While loop while (brains.size > 0) { zombie eat brains }
  • Do-While loop do { zombie eat brains } while (brains.size > 0)
  • Friendly advise Try use recursion instead of loops! And don’t feed zombies
  • For expression
  • For expression • Looks like a for-loop • Behaves as a swiss knife 
  • For + generator for (zombie <- zombieHorde) kill(zombie)
  • For + generator + filter for (zombie <- zombieHorde if zombie.isMoving) kill(zombie)
  • For + generator + filter + yield This will produce a new collection! val killedZombies = for (zombie <- zombieHorde if !zombie.isMoving) yield zombie
  • For expression Can be used instead of map, filter and flatMap combination
  • Pattern Matching
  • Simple matching val status: String = "R” val translated = status match { case "R" => "running” case "D" => "digesting” case "E" => "eating brainz” case _ => "X3" }
  • Structure matching case class User(name: String, lastname: String, age: Int) val users = List( User("Alexey", "Migutsky", 25), User("Alexander", "Albul", 27), User("John", "Doe", 99) ) val determined = users.map { case User("Alexey", _, _) => "L” case User("Alexander", _, _) => "A” case _ => "X3" }.mkString(",") // L,A,X3
  • Structure matching def describe(list: List[Int]) { list match { case first :: second :: third :: tail => println("First case") case head :: tail => println("Second case") case Nil => println("Empty list") } } describe(List(1,2,3)) // First case describe(List(1, 2)) // Second case describe(List()) // Empty list
  • Exception handling try { //something } catch { case e: IllegalArgumentException => println("Illegal argument") case _ => println("Unknown exception") }
  • Implicits
  • Implicits The compiler can insert parameters and call conversion methods automatically based on the types used This behavior can be achieved using the implicit modifier
  • #1 - Implicit parameters #2 – Implicit type conversion #3 – “Pimp my Library”
  • Implicit parameters case class Context(data: List[String]) implicit val context = Context(List("a", "b", "c")) object SomeService { def printCtx(implicit ctx: Context) = println(ctx.data.mkString(",")) } SomeService.printCtx // a,b,c
  • Implicit type conversion Compiler will use the implicit conversion method automatically! case class User(first: String, last: String) def printUserInfo(user: User) { println("User name is: " + user.first + ", last name is: " + user.last) } implicit def stringToUser(userString: String): User = { val split = userString.split(" ") User(split(0), split(1)) } printUserInfo("Alexander Albul")
  • Pimp My Library case class User(first: String, last: String) implicit class ExtendedString(str: String) { def toUser: User = { val split = str.split(" ") User(split(0), split(1)) } } def printUserInfo(user: User) { println("User name is: " + user.first + ", last name is: " + user.last) } printUserInfo("Alexander Albul".toUser)
  • Moar Sugar! For those who survived
  • Stuff : Object equality Use == to compare anything 1 == 1.0 // true List(1,2,3) == List(1,2,3) // true null == List(1,2,3) // false List(1,2) == "string" // false
  • Stuff : Object equality The equality operator == do the following 1. Check the left side for null 2. If left side is not null, then call equals method Scala provides a facility for comparing reference equality, as well, under the name eq. However, eq and its opposite, ne, only apply to objects that directly map to Java objects.
  • Stuff : Packages and Imports • Scala code resides in the Java platform’s global hierarchy of packages. • Package definition is at the top of the file. • The structure is reflected on file system. package graveyard class Zombie
  • Stuff : Packages and Imports • The other way you can place code into packages in Scala is more like C# namespaces (called packaging) • Packages can be nested package graveyard { package gravestone { class Zombie } }
  • Stuff : Packages and Imports In Scala, packages and their members can be imported using import clauses. Imported items can then be accessed by a simple name like Zombie , as opposed to requiring a qualified name like graveyard.gravestone.Zombie. // import Zombie import graveyard.gravestone.Zombie // import all undead horde import graveyard._
  • Stuff : Packages and Imports • Imports may appear anywhere • Import may refer to objects (singleton or regular) in addition to packages • Import let you rename and hide some of the imported members // please don't do this IRL: aliases must be reasonable! import graveyard.gravestone.{Zombie => RoseBush} def hideUndead(): RoseBush = { import graveyard.gravestone.{Zombie => OldMan} new OldMan() }
  • Stuff : Identifiers 1. CamelCase 2. Alphanumeric for variables – letters + digits 3. Do not use starting $ - it is reserved for compiler variables 4. Do not use _ in names – underscore has other usages 5. Constants has first uppercase letter – math.Pi
  • Stuff : Method call Method with 0 parameter can be called without () Method with 1 parameter can be called using infix notation new Test().method // method call new Test().function // res1: () => Unit = <function0> new Test() method1 10 // 13
  • Stuff : Method call Use higher-order functions with infix notation, but not with mixed notation List("abcd","zyxwvu").map (_.toUpperCase).filter (_.length > 5) // bad! List("abcd","zyxwvu") map (_.toUpperCase) filter (_.length > 5) // good
  • Stuff : Method calls Use infix notation only with methods without side effects (which do not modify internal class state) List(1,2) mkString "" // ok new CustomDataset() add "some value" // not ok
  • Lazy evaluation An expression that has a value, but that is not evaluated until it's actually needed (in another words – until the value is actually read).
  • Call by-name parameter Lazy evaluated parameter def callByValue(x: Int) = { //parameter get evaluated upon function call println("x1=" + x) println("x2=" + x) } def callByName(x: => Int) = { println("x1=" + x) // parameter get evaluated here println("x2=" + x) // parameter get evaluated again }
  • Lazy initialization When a val is declared with the lazy modifier the righthand side of the value (the definition) will not be executed until the first time the value is accessed. val normal = 5 // evaluated immediately lazy val lzy = 5 // evaluated only upon first read
  • Stuff : Streams A stream is like a list except that its elements are computed lazily. Because of this, a stream can be infinitely long. Only those elements requested will be computed. Otherwise, streams have the same performance characteristics as lists.
  • Stuff : Streams Classical example: Fibonacci sequence def fibFrom(a: Int, b: Int): Stream[Int] = { a #:: fibFrom(b, a + b) }
  • Tail recursion Scala compiler can transform a recursive call into a loop so that it won’t use stack for evaluation! But it can apply its magic only in case of tail recursion.
  • Tail recursion Tail recursion is simple: If the last evaluated expression in a function only makes a recursive call, but does not make additional computations, than the function is tail recursive!
  • Tail recursion : example def boom(x: Int): Int = if (x == 0) throw new Exception("boom!") else boom(x - 1) + 1 @tailrec def bang(x: Int): Int = if (x == 0) throw new Exception("bang!") else bang(x - 1)
  • Monads
  • Monad Monad is a name of abstraction. 1. 2. 3. 4. Chain function calls “Container” type Composable with each other Wrap types, which are stored in the monad, into a monad type (like zombies – their bites turn everyone in a zombie)
  • Monad You may have been working with monads already! • Promises are monads! • jQuery object is a monad! • Futures (partial monadic API)
  • Monad Every monad can: • Wrap a value into a Monad type • Unwrap a value from a Monad type • Work transparently with wrapped value using Monad interface
  • Monads like Zombies Every good zombie can: • Turn a person into a zombie • Turn back into a person if cured • Communicate with other zombies as if those were people
  • Monads Monad is a really tough topic for beginners! Spend at least a week cranking the theory to create you own vision of this abstraction!
  • Option Scala has a standard type named Option for optional values. One can say, that Option is a replacement for Nullobject pattern. It eliminates the null-checks in the code! It eliminates Null-Pointer Exceptions!
  • Option Option have two forms: • Some(x) • None Scala collections do not return nulls, they return None!
  • Option The most common way to take optional values apart is through a pattern match. def show(x: Option[String]) = x match { case Some(s) => println(s) case None => println("?") }
  • Option Option is a collection! Well, it is actually a single-value container  You can use map, filter, flallen, for-comprehension and other collection API methods with Option! http://danielwestheide.com/blog/2012/12/19/the-neophytes-guide-to-scala-part-5-the-option-type.html http://blog.tmorris.net/scalaoption-cheat-sheet/
  • Option : Practices • You should avoid null as much as possible in Scala • Use Option when you can return something like a “no value” • Do not use null-checks in scala, use collection API/pattern matching over Option
  • Try A monad for exception handling. Its main purpose is to wrap the exception and pass it around the code (e.g. to another execution context) Was developed by Twitter team to pass exceptions across cluster nodes.
  • Try Try has two forms: • Failure[Throwable] • Success[T]
  • Try : Example Try(Integer.parseInt("3")).getOrElse(println("Sorry, I failed"))
  • Try : Practices • Use Try rather than a catch block for handling unexpected failure. • Use Try when working with Future. • Exposing Try in a public API has a similiar effect as a checked exception. Consider using exceptions instead.
  • Underscore Wildcard on steroids!
  • Underscore usages Tons of them! 1. “Placeholder syntax” List(1, 2, 3) map (_ + 2) 2. Partially applied functions List(1, 2, 3) foreach println _ 3. Wildcard pattern Some(5) match { case Some(_) => println("Yes") } 4. Wildcard imports import java.util._ http://stackoverflow.com/questions/8000903/what-are-all-the-uses-of-an-underscore-in-scala
  • Thanks! val you = new Developer[Any] with ScalaKnowledge
  • Resources • Scala Twitter School [link] • Effective Scala [link] • Scala for Java Programmers [link] • The Neophyte’s Guide to Scala [link] [book] • Functional Programming Principles in Scala @ Coursera [link] • Programming in Scala [book] • ScalaUA skype chat [link]