Scala
Programming Language
Scala
Overview
Scala is a multi-paradigm programming language that runs on the JVM, combining functional programming and object-oriented programming.
Details
Scala (Scalable Language) is a programming language developed by Martin Odersky in 2003 that integrates both functional and object-oriented programming paradigms and runs on the Java Virtual Machine (JVM). It features static typing with type inference for concise code, emphasizes immutability, and provides higher-order functions, pattern matching, and flexible inheritance through traits. It is widely adopted in large-scale distributed systems and big data processing frameworks such as Apache Spark, Apache Kafka, and Akka, particularly providing powerful capabilities in concurrent processing and reactive programming. High compatibility with Java allows leveraging existing Java libraries while enabling practical application development with the benefits of functional programming.
Code Examples
Hello World
// Basic output
object HelloWorld extends App {
println("Hello, World!")
// Output using variables
val message = "Hello, Scala!"
println(message)
// String interpolation
val name = "John"
val age = 25
println(s"My name is $name and I am $age years old.")
// Format strings
printf("Number: %d, Float: %.2f%n", 42, 3.14159)
}
// Using main function
object HelloWorldMain {
def main(args: Array[String]): Unit = {
println("Hello, World!")
}
}
Variables and Data Types
object VariablesAndTypes extends App {
// Immutable variables (val)
val immutableInt: Int = 42
val immutableString: String = "string"
val immutableDouble: Double = 3.14159
val immutableBoolean: Boolean = true
// Mutable variables (var)
var mutableInt: Int = 100
var mutableString: String = "mutable"
// Type inference
val inferredInt = 42 // Inferred as Int
val inferredString = "text" // Inferred as String
// Collection types
val list: List[Int] = List(1, 2, 3, 4, 5)
val array: Array[String] = Array("a", "b", "c")
val map: Map[String, Int] = Map("one" -> 1, "two" -> 2, "three" -> 3)
val set: Set[Int] = Set(1, 2, 3, 2, 1) // Duplicates removed
// Tuples
val tuple2: (String, Int) = ("John", 25)
val tuple3: (String, Int, Boolean) = ("Jane", 30, true)
// Option type (alternative to null)
val someValue: Option[String] = Some("has value")
val noneValue: Option[String] = None
// Output examples
println(s"Integer: $immutableInt")
println(s"List length: ${list.length}")
println(s"Map value: ${map("one")}")
println(s"Tuple first element: ${tuple2._1}")
// Variable modification
mutableInt = 200
println(s"Modified value: $mutableInt")
}
Conditional Statements
object ConditionalStatements extends App {
val score = 85
// Basic if expression
val grade = if (score >= 90) {
"A"
} else if (score >= 80) {
"B"
} else if (score >= 70) {
"C"
} else {
"D"
}
println(s"Score: $score, Grade: $grade")
// Multiple condition combinations
val age = 20
val hasLicense = true
val canDrive = if (age >= 18 && hasLicense) {
"You can drive"
} else if (age >= 18) {
"Please get a license"
} else {
"Please get a license after turning 18"
}
println(canDrive)
// Pattern matching
val day = "Wednesday"
val dayType = day match {
case "Monday" | "Tuesday" | "Wednesday" | "Thursday" | "Friday" => "Weekday"
case "Saturday" | "Sunday" => "Weekend"
case _ => "Unknown"
}
println(s"$day is a $dayType")
// Pattern matching with values
val number = 42
val numberDescription = number match {
case 0 => "Zero"
case n if n > 0 && n <= 10 => "Number between 1 and 10"
case n if n > 10 && n <= 100 => "Number between 11 and 100"
case _ => "Other number"
}
println(s"$number is $numberDescription")
// Option pattern matching
val optionalValue: Option[String] = Some("value")
val result = optionalValue match {
case Some(value) => s"Has value: $value"
case None => "No value"
}
println(result)
}
Collections and Higher-Order Functions
object CollectionsAndHigherOrderFunctions extends App {
// List operations
val numbers = List(1, 2, 3, 4, 5, 6, 7, 8, 9, 10)
// map function (transformation)
val squares = numbers.map(x => x * x)
val squaresShort = numbers.map(_ * _) // More concise syntax
println(s"Squares: $squares")
// filter function (filtering)
val evenNumbers = numbers.filter(x => x % 2 == 0)
val evenNumbersShort = numbers.filter(_ % 2 == 0)
println(s"Even numbers: $evenNumbers")
// reduce function (folding)
val sum = numbers.reduce((a, b) => a + b)
val sumShort = numbers.reduce(_ + _)
println(s"Sum: $sum")
// fold function (folding with initial value)
val product = numbers.fold(1)((a, b) => a * b)
println(s"Product: $product")
// Function chaining
val result = numbers
.filter(_ % 2 == 0) // Even numbers only
.map(_ * 3) // Multiply by 3
.filter(_ > 10) // Greater than 10
.sum // Sum
println(s"Chain processing result: $result")
// for expression (comprehension)
val combinations = for {
x <- List(1, 2, 3)
y <- List('a', 'b', 'c')
if x > 1 // Guard condition
} yield (x, y)
println(s"Combinations: $combinations")
// Nested for expression
val matrix = List(List(1, 2, 3), List(4, 5, 6), List(7, 8, 9))
val flattenedDoubled = for {
row <- matrix
element <- row
if element % 2 == 0
} yield element * 2
println(s"Flattened and doubled: $flattenedDoubled")
// Map operations
val grades = Map("John" -> 85, "Jane" -> 92, "Bob" -> 78)
// Map transformation
val adjustedGrades = grades.map { case (name, grade) =>
name -> (grade + 5)
}
println(s"Adjusted grades: $adjustedGrades")
// Map filtering
val highGrades = grades.filter { case (_, grade) => grade >= 80 }
println(s"High grades: $highGrades")
}
Function Definition and Higher-Order Functions
object FunctionsAndHigherOrder extends App {
// Basic function definition
def greet(name: String): String = {
s"Hello, $name!"
}
// Single expression function (omit braces)
def square(x: Int): Int = x * x
// Default arguments
def calculateArea(width: Double, height: Double = 10.0): Double = {
width * height
}
// Variable arguments
def sum(numbers: Int*): Int = {
numbers.sum
}
// Higher-order function (takes function as argument)
def applyOperation(x: Int, y: Int, operation: (Int, Int) => Int): Int = {
operation(x, y)
}
// Function returning function
def createMultiplier(factor: Int): Int => Int = {
(x: Int) => x * factor
}
// Anonymous functions (lambda functions)
val add = (x: Int, y: Int) => x + y
val multiply = (x: Int, y: Int) => x * y
// Partial application
def addThreeNumbers(x: Int, y: Int, z: Int): Int = x + y + z
val addFive = addThreeNumbers(5, _, _) // Fix first argument to 5
// Currying
def curriedAdd(x: Int)(y: Int)(z: Int): Int = x + y + z
val addTen = curriedAdd(10) _
val addTenAndFive = addTen(5)
// Function usage examples
println(greet("Alice"))
println(s"Area: ${calculateArea(5.0)}")
println(s"Sum: ${sum(1, 2, 3, 4, 5)}")
println(s"Operation result: ${applyOperation(10, 20, add)}")
println(s"Operation result: ${applyOperation(10, 20, multiply)}")
val doubler = createMultiplier(2)
println(s"Double: ${doubler(15)}")
println(s"Partial application: ${addFive(10, 15)}")
println(s"Currying: ${addTenAndFive(7)}")
// Recursive function
def factorial(n: Int): Int = {
if (n <= 1) 1
else n * factorial(n - 1)
}
// Tail recursion optimization
@scala.annotation.tailrec
def factorialTailRec(n: Int, acc: Int = 1): Int = {
if (n <= 1) acc
else factorialTailRec(n - 1, n * acc)
}
println(s"Factorial: ${factorial(5)}")
println(s"Tail recursive factorial: ${factorialTailRec(5)}")
}
Classes and Object-Oriented Programming
// Basic class definition
class Person(val name: String, var age: Int) {
// Private field
private var _id: String = ""
// Secondary constructor
def this(name: String, age: Int, id: String) = {
this(name, age)
this._id = id
}
// Method
def greet(): String = s"Hello, I'm $name."
def haveBirthday(): Unit = {
age += 1
println(s"$name is now $age years old.")
}
// getter/setter
def id: String = _id
def id_=(newId: String): Unit = {
if (newId.nonEmpty) _id = newId
}
override def toString: String = s"Person($name, $age)"
}
// Inheritance
abstract class Animal(val name: String) {
def makeSound(): String // Abstract method
def introduce(): String = s"I'm an animal named $name."
}
class Dog(name: String, val breed: String) extends Animal(name) {
override def makeSound(): String = "Woof"
def fetch(): String = s"$name fetched the ball."
}
class Cat(name: String, val color: String) extends Animal(name) {
override def makeSound(): String = "Meow"
def purr(): String = s"$name is purring."
}
// Trait
trait Flyable {
def fly(): String = "Flying in the sky"
def altitude: Double // Abstract field
}
trait Swimmable {
def swim(): String = "Swimming in water"
}
// Multiple trait mixin
class Duck(name: String) extends Animal(name) with Flyable with Swimmable {
override def makeSound(): String = "Quack"
override val altitude: Double = 100.0
override def fly(): String = s"$name is flying at ${altitude}m altitude"
override def swim(): String = s"$name is swimming in the pond"
}
// Case class
case class Point(x: Double, y: Double) {
def distance(other: Point): Double = {
math.sqrt(math.pow(x - other.x, 2) + math.pow(y - other.y, 2))
}
}
// Singleton object
object MathUtils {
val PI: Double = 3.14159
def circleArea(radius: Double): Double = PI * radius * radius
def max(a: Int, b: Int): Int = if (a > b) a else b
}
// Usage example
object ObjectOrientedExample extends App {
// Class instantiation
val person1 = new Person("John Doe", 30)
val person2 = new Person("Jane Smith", 25, "ID001")
println(person1.greet())
person1.haveBirthday()
// Inheritance and polymorphism
val animals: List[Animal] = List(
new Dog("Buddy", "Golden Retriever"),
new Cat("Whiskers", "Tabby"),
new Duck("Donald")
)
animals.foreach { animal =>
println(s"${animal.introduce()} Sound: ${animal.makeSound()}")
}
// Trait usage
val duck = new Duck("Daffy")
println(duck.fly())
println(duck.swim())
// Case class usage
val point1 = Point(0, 0)
val point2 = Point(3, 4)
println(s"Distance: ${point1.distance(point2)}")
// Pattern matching with case class decomposition
point1 match {
case Point(0, 0) => println("Origin point")
case Point(x, 0) => println(s"Point on x-axis ($x, 0)")
case Point(0, y) => println(s"Point on y-axis (0, $y)")
case Point(x, y) => println(s"General point ($x, $y)")
}
// Singleton object usage
println(s"Circle area: ${MathUtils.circleArea(5.0)}")
println(s"Maximum: ${MathUtils.max(10, 20)}")
}
Concurrency and Future
import scala.concurrent.{Future, ExecutionContext}
import scala.util.{Success, Failure}
import scala.concurrent.duration._
object ConcurrencyExample extends App {
// Implicit ExecutionContext
implicit val ec: ExecutionContext = ExecutionContext.global
// Basic Future
val future1: Future[Int] = Future {
Thread.sleep(1000)
42
}
val future2: Future[String] = Future {
Thread.sleep(500)
"Hello, Future!"
}
// Transform Future result
val doubledFuture: Future[Int] = future1.map(_ * 2)
// Combine Futures
val combinedFuture: Future[String] = for {
number <- future1
text <- future2
} yield s"$text Number: $number"
// Handle Future completion
future1.onComplete {
case Success(value) => println(s"Success: $value")
case Failure(exception) => println(s"Failure: ${exception.getMessage}")
}
// Execute multiple Futures in parallel
val futures = List(
Future { Thread.sleep(100); 1 },
Future { Thread.sleep(200); 2 },
Future { Thread.sleep(150); 3 }
)
val allResults: Future[List[Int]] = Future.sequence(futures)
// Error handling
val riskyFuture: Future[Int] = Future {
if (scala.util.Random.nextBoolean()) {
throw new RuntimeException("An error occurred")
}
100
}
val safeFuture: Future[Int] = riskyFuture.recover {
case _: RuntimeException => 0
}
// Wait for Future result (not recommended in actual applications)
import scala.concurrent.Await
try {
val result = Await.result(combinedFuture, 2.seconds)
println(s"Result: $result")
} catch {
case _: java.util.concurrent.TimeoutException =>
println("Timeout occurred")
}
// Wait for application termination
Thread.sleep(2000)
}
Special Features
Advanced Pattern Matching
object AdvancedPatternMatching extends App {
// Sealed classes and pattern matching
sealed trait Expression
case class Number(value: Double) extends Expression
case class Variable(name: String) extends Expression
case class Add(left: Expression, right: Expression) extends Expression
case class Multiply(left: Expression, right: Expression) extends Expression
def evaluate(expr: Expression, variables: Map[String, Double]): Double = expr match {
case Number(value) => value
case Variable(name) => variables.getOrElse(name, 0.0)
case Add(left, right) => evaluate(left, variables) + evaluate(right, variables)
case Multiply(left, right) => evaluate(left, variables) * evaluate(right, variables)
}
// List pattern matching
def listPattern(list: List[Int]): String = list match {
case Nil => "Empty list"
case head :: Nil => s"Single element: $head"
case head :: tail => s"Head: $head, Tail: $tail"
}
// Pattern matching with guard conditions
def classifyNumber(x: Int): String = x match {
case n if n < 0 => "Negative number"
case 0 => "Zero"
case n if n > 0 && n <= 10 => "1 to 10"
case n if n > 10 => "Greater than 10"
}
// Usage examples
val expr = Add(Number(10), Multiply(Variable("x"), Number(5)))
val vars = Map("x" -> 3.0)
println(s"Calculation result: ${evaluate(expr, vars)}")
println(listPattern(List(1, 2, 3)))
println(classifyNumber(5))
}
Implicit Conversions and Type Classes
object ImplicitsExample extends App {
// Implicit conversions
implicit class StringOps(s: String) {
def isPalindrome: Boolean = s == s.reverse
def toSnakeCase: String = s.replaceAll("([A-Z])", "_$1").toLowerCase.dropWhile(_ == '_')
}
// Implicit parameters
implicit val defaultTimeout: Int = 5000
def connectToServer(host: String)(implicit timeout: Int): String = {
s"Connecting to $host within ${timeout}ms"
}
// Type class pattern
trait Printable[T] {
def format(value: T): String
}
implicit val intPrintable: Printable[Int] = new Printable[Int] {
def format(value: Int): String = s"Integer: $value"
}
implicit val stringPrintable: Printable[String] = new Printable[String] {
def format(value: String): String = s"String: '$value'"
}
def print[T](value: T)(implicit printer: Printable[T]): Unit = {
println(printer.format(value))
}
// Usage examples
println("racecar".isPalindrome)
println("CamelCase".toSnakeCase)
println(connectToServer("localhost"))
print(42)
print("Hello")
}
Monads and for-expressions
object MonadExample extends App {
// Option monad
def safeDivide(x: Double, y: Double): Option[Double] = {
if (y != 0) Some(x / y) else None
}
def safeSquareRoot(x: Double): Option[Double] = {
if (x >= 0) Some(math.sqrt(x)) else None
}
// Monadic operations
val result1 = for {
division <- safeDivide(10, 2)
sqrt <- safeSquareRoot(division)
} yield sqrt
println(s"Safe calculation result: $result1")
// Either monad (error handling)
sealed trait ValidationError
case object InvalidAge extends ValidationError
case object InvalidEmail extends ValidationError
def validateAge(age: Int): Either[ValidationError, Int] = {
if (age >= 0 && age <= 150) Right(age) else Left(InvalidAge)
}
def validateEmail(email: String): Either[ValidationError, String] = {
if (email.contains("@")) Right(email) else Left(InvalidEmail)
}
case class User(age: Int, email: String)
def createUser(age: Int, email: String): Either[ValidationError, User] = {
for {
validAge <- validateAge(age)
validEmail <- validateEmail(email)
} yield User(validAge, validEmail)
}
println(createUser(25, "[email protected]"))
println(createUser(-5, "invalid-email"))
}
Versions
Version | Status | Key Features | Release Year |
---|---|---|---|
Scala 3 (Dotty) | Latest | New syntax, improved type system, macro overhaul | 2021 |
Scala 2.13 | Current | Collection library overhaul, performance improvements | 2019 |
Scala 2.12 | Maintained | Java 8 support, SAM types, lambda optimization | 2016 |
Scala 2.11 | Legacy | Modularization, macro stabilization | 2014 |
Reference Pages
Official Documentation
- Scala Documentation - Official documentation
- Scala 3 Documentation - Scala 3 specific documentation
- Scala Standard Library - Standard library API
Learning Resources
- Scala Exercises - Interactive learning site
- Functional Programming in Scala - Functional programming guide
- Rock the JVM - Scala learning platform
Frameworks and Libraries
- Apache Spark - Large-scale data processing framework
- Akka - Actor model concurrency framework
- Play Framework - Web application framework