#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
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
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
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
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
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
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
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
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
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
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
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.