Scala Operators and Expressions
In Scala, an expression like 3 + 4 is not a special built-in operation at all — it is shorthand infix syntax for the method call 3.+(4), since Int is itself a class with a + method defined on it. This uniformity extends throughout the language: almost every construct in Scala, including if/else and code blocks wrapped in {}, is an expression that evaluates to a value, rather than a statement that merely performs a side effect the way many constructs do in Java.
Cricket analogy: In Scala, writing 3 + 4 is really shorthand for calling 3.+(4) — like how a scorer writing '4' on the board is really shorthand for the umpire's raised-arm signal confirming a boundary; and just as every ball bowled produces a countable outcome, every Scala construct, including if blocks, produces a value rather than being a silent statement.
Arithmetic, Comparison, and Logical Operators
Scala provides the familiar arithmetic (+ - * / %), comparison (== != < > <= >=), and logical (&& ||, short-circuiting) operators, but with one important difference from Java: == performs structural (value) equality by default, delegating to .equals, rather than reference equality. This means two separately created case class instances with identical field values are considered ==, whereas checking whether two references point to the exact same object in memory requires the separate eq method.
Cricket analogy: Scala's == performing structural (value) equality rather than Java-style reference equality is like two identical scorecards from different matches being judged 'equal' if every run, wicket, and over matches exactly — Scala compares the actual runs recorded, not which physical scorebook they're written in.
Operators Are Just Methods
Because operators are methods, you can define your own on any class you write — for example, a Vector2D case class can implement def +(other: Vector2D): Vector2D so that v1 + v2 reads naturally while actually invoking your custom addition logic. This is a genuine language feature, not a hack, but it comes with a responsibility: an overloaded operator's behavior should map intuitively to what a reader would expect from that symbol, or the resulting code becomes cryptic rather than clear.
Cricket analogy: Defining a custom + operator on a Scala class, such as def +(other: Score): Score, is like the ICC formally defining what it means to 'add' two innings' worth of Duckworth-Lewis-adjusted par scores — you're specifying precisely what combination means for your own custom type, not just relying on plain arithmetic.
Expressions vs Statements: if and Blocks Return Values
Because if/else is an expression, val result = if (x > 0) "positive" else "non-positive" is perfectly valid Scala — the whole conditional evaluates to whichever branch's value matches, and can be assigned directly to a val. The same applies to blocks: { statement1; statement2; finalExpr } evaluates to finalExpr, the value of its last line. This is precisely why Scala has no separate ternary operator (?:) the way Java does — if/else already fills that role while also working as a full multi-line conditional.
Cricket analogy: In Scala, val result = if (runs > 200) "Strong total" else "Below par" treats if as an expression that yields a value directly, much like a match referee's on-field decision immediately produces a result (out or not out) that's recorded on the scorecard, rather than the decision existing separately from the outcome.
// Operators are just methods written in infix notation
val sum = 3 + 4 // desugars to: 3.+(4)
val isEqual = sum == 7 // desugars to: sum.==(7) -> structural equality
// Comparison and logical operators
val isAdult = age >= 18 && hasId
// Custom operator defined on a case class
case class Vector2D(x: Double, y: Double) {
def +(other: Vector2D): Vector2D = Vector2D(x + other.x, y + other.y)
def *(scalar: Double): Vector2D = Vector2D(x * scalar, y * scalar)
}
val v1 = Vector2D(1.0, 2.0)
val v2 = Vector2D(3.0, 4.0)
val v3 = v1 + v2 // Vector2D(4.0, 6.0), calls v1.+(v2)
// if is an expression: it evaluates to a value
val label: String =
if (v3.x > 3.0) "far right"
else "near origin"
println(label)
Scala's == performs structural equality by default (delegating to .equals), which is almost always what you want — two case class instances with identical field values are ==, even if they're different objects in memory. If you specifically need reference equality (are they the literal same object?), use eq instead.
Just because Scala lets you define operators like +, -, or even custom symbols like <+> on your own types doesn't mean you always should. Overusing symbolic operator names for non-obvious operations makes code harder to read for anyone unfamiliar with your API — reserve operator overloading for cases where the symbol's meaning is genuinely intuitive, like arithmetic on a Vector2D or Money type.
- In Scala, operators like + and - are ordinary method calls written in infix notation: a + b means a.+(b).
- Because everything is a method call, you can define custom operators on your own classes.
- Scala's == performs structural (value) equality by default, unlike Java's reference-comparing ==; use eq for reference equality.
- if/else in Scala is an expression that returns a value, so it can be assigned directly to a val.
- Blocks {} evaluate to the value of their last expression, which is why Scala has no separate ternary operator.
- Logical operators && and || short-circuit, just as in most C-family languages.
- Overloading symbolic operators should be reserved for cases where the meaning is genuinely intuitive to readers.
Practice what you learned
1. What does `a + b` actually mean in Scala under the hood?
2. How does Scala's == operator behave by default?
3. What does an `if/else` expression in Scala do that's different from a Java if statement?
4. Why does Scala not have a ternary operator (?:)?
5. Which operator checks reference (identity) equality rather than structural equality in Scala?
Was this page helpful?
You May Also Like
vals, vars, and Types
How Scala's val/var distinction enforces immutability by default, and how the static type system infers and checks types at compile time.
What Is Scala?
An introduction to Scala as a statically typed, JVM-based language that fuses object-oriented and functional programming paradigms.
Your First Scala Program
A hands-on walkthrough of writing, compiling, and running a complete Scala program, from the @main entry point to reading input from the console.
Related Reading
Related Study Notes in Programming
Browse all study notesApache Spark Study Notes
Programming · 30 topics
ProgrammingApache Flink Study Notes
Programming · 30 topics
ProgrammingHadoop Study Notes
Programming · 30 topics
ProgrammingSnowflake Study Notes
Programming · 30 topics
ProgrammingApache Airflow Study Notes
Programming · 30 topics
Programmingdbt (Data Build Tool) Study Notes
Programming · 30 topics