Scala Conditional Statements
Scala provides multiple conditional control structures, including if-else statements, match expressions, and more. Unlike Java, all conditional statements in Scala are expressions and return values.
if-else Expression
Basic if-else
scala
object BasicIfElse {
def main(args: Array[String]): Unit = {
val age = 18
// Basic if-else
if (age >= 18) {
println("Adult")
} else {
println("Minor")
}
// if-else as expression
val status = if (age >= 18) "Adult" else "Minor"
println(s"Status: $status")
// Single-line if-else
val message = if (age >= 18) "Can vote" else "Cannot vote"
println(message)
}
}Multiple if-else
scala
object MultipleIfElse {
def main(args: Array[String]): Unit = {
val score = 85
val grade = if (score >= 90) {
"A"
} else if (score >= 80) {
"B"
} else if (score >= 70) {
"C"
} else if (score >= 60) {
"D"
} else {
"F"
}
println(s"Score: $score, Grade: $grade")
// More complex conditions
val temperature = 25
val weather = if (temperature > 30) {
"Hot"
} else if (temperature > 20) {
"Warm"
} else if (temperature > 10) {
"Cool"
} else {
"Cold"
}
println(s"Temperature: ${temperature}°C, Weather: $weather")
}
}Nested if-else
scala
object NestedIfElse {
def main(args: Array[String]): Unit = {
val age = 25
val hasLicense = true
val hasInsurance = true
val canDrive = if (age >= 18) {
if (hasLicense) {
if (hasInsurance) {
"Can drive"
} else {
"Needs insurance"
}
} else {
"Needs license"
}
} else {
"Not old enough"
}
println(canDrive)
// Simplified using logical operators
val canDriveSimple = if (age >= 18 && hasLicense && hasInsurance) {
"Can drive"
} else {
"Cannot drive"
}
println(canDriveSimple)
}
}Match Expression
Basic Match Expression
scala
object BasicMatch {
def main(args: Array[String]): Unit = {
val dayOfWeek = 3
val dayName = dayOfWeek match {
case 1 => "Monday"
case 2 => "Tuesday"
case 3 => "Wednesday"
case 4 => "Thursday"
case 5 => "Friday"
case 6 => "Saturday"
case 7 => "Sunday"
case _ => "Invalid day" // Default case
}
println(s"Day $dayOfWeek is $dayName")
// Match strings
val fruit = "apple"
val color = fruit match {
case "apple" => "Red"
case "banana" => "Yellow"
case "orange" => "Orange"
case "grape" => "Purple"
case _ => "Unknown color"
}
println(s"$fruit color is $color")
}
}Conditional Match
scala
object ConditionalMatch {
def main(args: Array[String]): Unit = {
val number = 15
val description = number match {
case n if n < 0 => "Negative"
case n if n == 0 => "Zero"
case n if n > 0 && n < 10 => "Single digit positive"
case n if n >= 10 && n < 100 => "Two digit positive"
case _ => "Large number"
}
println(s"$number is $description")
// Match ranges
val grade = 85
val level = grade match {
case g if g >= 90 => "Excellent"
case g if g >= 80 => "Good"
case g if g >= 70 => "Medium"
case g if g >= 60 => "Pass"
case _ => "Fail"
}
println(s"Score $grade corresponds to level $level")
}
}Type Matching
scala
object TypeMatching {
def main(args: Array[String]): Unit = {
def processValue(value: Any): String = value match {
case s: String => s"String: $s"
case i: Int => s"Integer: $i"
case d: Double => s"Floating point: $d"
case b: Boolean => s"Boolean: $b"
case list: List[_] => s"List with ${list.length} elements"
case map: Map[_, _] => s"Map with ${map.size} entries"
case _ => "Unknown type"
}
println(processValue("Hello")) // String: Hello
println(processValue(42)) // Integer: 42
println(processValue(3.14)) // Floating point: 3.14
println(processValue(true)) // Boolean: true
println(processValue(List(1, 2, 3))) // List with 3 elements
println(processValue(Array(1, 2))) // Unknown type
}
}Collection Matching
scala
object CollectionMatching {
def main(args: Array[String]): Unit = {
def analyzeList(list: List[Int]): String = list match {
case Nil => "Empty list"
case head :: Nil => s"Single element: $head"
case head :: tail => s"Head: $head, Tail length: ${tail.length}"
}
println(analyzeList(List())) // Empty list
println(analyzeList(List(1))) // Single element: 1
println(analyzeList(List(1, 2, 3))) // Head: 1, Tail length: 2
// Match specific patterns
def matchPattern(list: List[Int]): String = list match {
case List(1, 2, 3) => "Exactly 1, 2, 3"
case List(1, _*) => "List starting with 1"
case List(_, _, 3) => "Three element list with third element 3"
case x :: y :: _ if x > y => "First two elements decreasing"
case _ => "Other pattern"
}
println(matchPattern(List(1, 2, 3))) // Exactly 1, 2, 3
println(matchPattern(List(1, 4, 5))) // List starting with 1
println(matchPattern(List(2, 1, 3))) // Three element list with third element 3
println(matchPattern(List(5, 3, 1))) // First two elements decreasing
}
}Advanced Conditional Expressions
Option Type Conditional Handling
scala
object OptionConditionals {
def main(args: Array[String]): Unit = {
def findUser(id: Int): Option[String] = {
if (id > 0) Some(s"User$id") else None
}
val userId = 5
val user = findUser(userId)
// Use match to handle Option
val message = user match {
case Some(name) => s"Found user: $name"
case None => "User does not exist"
}
println(message)
// Use if-else to handle Option
val result = if (user.isDefined) {
s"Username: ${user.get}"
} else {
"User not found"
}
println(result)
// Use getOrElse
val userName = user.getOrElse("Anonymous user")
println(s"User: $userName")
}
}Functional Conditional Handling
scala
object FunctionalConditionals {
def main(args: Array[String]): Unit = {
val numbers = List(1, 2, 3, 4, 5, 6, 7, 8, 9, 10)
// Use filter for conditional filtering
val evenNumbers = numbers.filter(_ % 2 == 0)
println(s"Even numbers: $evenNumbers")
// Use partition to split
val (evens, odds) = numbers.partition(_ % 2 == 0)
println(s"Evens: $evens")
println(s"Odds: $odds")
// Use find to locate
val firstEven = numbers.find(_ % 2 == 0)
println(s"First even: $firstEven")
// Use exists to check existence
val hasEven = numbers.exists(_ % 2 == 0)
println(s"Contains even numbers: $hasEven")
// Use forall to check all
val allPositive = numbers.forall(_ > 0)
println(s"All positive: $allPositive")
}
}Practical Examples
Grade Management System
scala
case class Student(name: String, score: Int)
object GradeSystem {
def getGrade(score: Int): String = score match {
case s if s >= 90 => "A"
case s if s >= 80 => "B"
case s if s >= 70 => "C"
case s if s >= 60 => "D"
case _ => "F"
}
def getStatus(score: Int): String = {
if (score >= 60) "Pass" else "Fail"
}
def analyzeStudent(student: Student): String = {
val grade = getGrade(student.score)
val status = getStatus(student.score)
student.score match {
case s if s >= 95 => s"${student.name}: Excellent student ($grade, $status)"
case s if s >= 85 => s"${student.name}: Good student ($grade, $status)"
case s if s >= 60 => s"${student.name}: Average student ($grade, $status)"
case _ => s"${student.name}: Needs help ($grade, $status)"
}
}
def main(args: Array[String]): Unit = {
val students = List(
Student("Zhang San", 95),
Student("Li Si", 87),
Student("Wang Wu", 72),
Student("Zhao Liu", 45)
)
students.foreach(student => println(analyzeStudent(student)))
}
}Simple State Machine
scala
sealed trait State
case object Idle extends State
case object Running extends State
case object Paused extends State
case object Stopped extends State
class StateMachine(private var currentState: State = Idle) {
def transition(action: String): State = {
currentState = (currentState, action) match {
case (Idle, "start") => Running
case (Running, "pause") => Paused
case (Running, "stop") => Stopped
case (Paused, "resume") => Running
case (Paused, "stop") => Stopped
case (Stopped, "reset") => Idle
case (state, _) =>
println(s"Invalid transition: $state -> $action")
state
}
currentState
}
def getCurrentState: State = currentState
}
object StateMachineExample {
def main(args: Array[String]): Unit = {
val machine = new StateMachine()
println(s"Initial state: ${machine.getCurrentState}")
println(s"After start: ${machine.transition("start")}")
println(s"After pause: ${machine.transition("pause")}")
println(s"After resume: ${machine.transition("resume")}")
println(s"After stop: ${machine.transition("stop")}")
println(s"After reset: ${machine.transition("reset")}")
}
}Best Practices
- Prioritize expressions: Take advantage of conditional statements returning values in Scala
- Use match instead of multiple if-else: When there are multiple conditions, match is clearer
- Avoid deep nesting: Use logical operators or early returns to reduce nesting
- Use Option to handle potentially null values: Avoid null pointer exceptions
- Leverage pattern matching power: Match types, collection structures, etc.
Mastering conditional control structures is the foundation for writing logically clear and maintainable code.