Scala
Completed
-
Section 1: Getting Started
-
Section 2: Core Syntax
-
Section 3: Object-Oriented Scala
-
Section 4: Functional Scala
-
Section 5: Collections in Depth
-
Section 6: Type System
-
Section 7: Concurrency and Ecosystem
-
Section 8: Practical Projects
-
Section 9: Interview Practice
-
Section 10: Data Structures and Algorithms in Scala
-
Section 11: More Practice Exercises
-
Section 12: Advanced Functional Patterns
-
Section 13: More Ecosystem
-
Section 14: Scala Collections Library Deep Dive
-
Section 15: Scala Standard Library Deep Dive
-
Section 16: Akka Ecosystem Deep Dive
-
Section 17: Cats and Cats Effect Deep Dive
-
Section 18: Play Framework Deep Dive
-
Section 19: Apache Spark with Scala Deep Dive
-
Section 20: Scala Build Tools Deep Dive
-
Section 21: Scala 3 Specific Features
-
90: Union and Intersection Types
-
Section 22: Scala Testing Deep Dive
-
Section 23: Functional Domain Modeling
-
Section 24: More Data Structures and Algorithms in Scala
-
Section 25: Scala for Data Engineering
-
Section 26: More Practical Projects
-
Section 27: More Interview and Review
-
Section 28: ZIO Ecosystem Deep Dive
-
Section 29: Scala for Machine Learning
-
Section 30: Scala Microservices Architecture
-
Section 31: Scala Type System Deep Dive
-
Section 32: More Practice and Drills
-
Section 33: Scala Performance Deep Dive
-
Section 34: Scala Ecosystem Tooling
-
Section 35: Scala for Reactive Systems
-
Section 36: More Real-World Case Studies
-
Section 37: Scala for Financial Systems
-
Section 38: Scala GraphQL and gRPC
-
Section 39: More Final Projects
-
Section 40: More Interview and Final Review
-
Section 41: Scala for Streaming Data
-
Section 42: Scala Security Practices
-
Section 43: More Language Deep Dive
-
Section 44: Scala Command-Line Tools
-
Section 45: Scala Documentation and Style
-
Section 46: Scala Dependency Management
-
Section 47: More Practical Backend Patterns
-
Section 48: Scala for Event-Driven Architecture
-
Section 49: More Practice Drills Round 2
-
Section 50: Scala Compiler Deep Dive
-
Section 51: Scala for Web Frontends
-
Section 52: More Data Engineering Practice
-
Section 53: Scala Observability
-
Section 54: More Advanced Practice Projects
-
Section 55: Scala for Legacy Java Integration
-
Section 56: More Testing Practice
-
Section 57: Final Mastery Review
-
Section 58: Scala History and Ecosystem Context
-
Section 59: More Concurrency Patterns
-
Section 60: Scala for Configuration Management
-
Section 61: More Domain Modeling Practice
167: Timed Mock Assessment on Core Scala
Alright, we've hit lesson 167. This is the "Mock Assessment" phase. Now, usually, a mock assessment is just a list of questions, but that's not how you actually learn to pass these things under pressure. Instead, I want to walk you through how I tackle a complex "core Scala" challenge when the clock is ticking. I've got a prompt here that asks me to build a LoyaltyCalculator that processes a stream of customer transactions and returns a tiered status based on specific business rules.
The goal: calculate a score where returns subtract points, high-value purchases add bonus points, and frequent small purchases provide a consistency multiplier. It sounds simple, but in a timed environment, it's easy to write "Java-in-Scala" rather than idiomatic Scala. Let's dive in.
Getting the basic logic down
First, I'll define my data structures. I need a Transaction case class. I'll start by trying to solve this with a simple filter and sum approach. It's the most intuitive way to start.
case class Transaction(id: String, amount: Double, isReturn: Boolean)
def calculateScore(txs: List[Transaction]): Double = {
val purchases = txs.filter(!_.isReturn).map(_.amount).sum
val returns = txs.filter(_.isReturn).map(_.amount).sum
purchases - returns
}
I ran this against a sample set, and it works, but it's inefficient. I'm traversing the list twice—once for purchases and once for returns. If this were a real-world dataset with millions of transactions, this would be a performance nightmare. In a core Scala assessment, the reviewer isn't just looking for the right answer; they're looking to see if you understand how to traverse a collection efficiently.
The MapValues trap
Now, the prompt adds a twist: the score needs to be calculated per customer from a master list of transactions. My first instinct is to use groupBy. Let's see where that leads me.
case class CustomerTx(customerId: Int, tx: Transaction)
def scoresPerCustomer(data: List[CustomerTx]): Map[Int, Double] = {
data.groupBy(_.customerId).mapValues { txs =>
val total = txs.map(_.tx).foldLeft(0.0)((acc, t) => if(t.isReturn) acc - t.amount else acc + t.amount)
total
}
}
I hit a snag here. If you're using Scala 2.13+, mapValues returns a MapView, not a strict Map. If I try to pass this result into another function that expects a concrete Map, I'm going to get a type mismatch error that'll waste five minutes of my timed session. I need to call .toMap at the end to materialize the results. It's a small detail, but these are the things that trip people up during assessments.
Tightening the loop for performance
I'm still not happy. The groupBy creates a bunch of intermediate lists. If I really want to show off "core Scala" proficiency, I should use a foldLeft to build the map in a single pass. It's a bit more verbose, but it's the "engineer's way" to do it.
I'll try to accumulate the totals directly into a map. I'll use getOrElse to handle the case where the customer isn't in the map yet.
def optimizedScores(data: List[CustomerTx]): Map[Int, Double] = {
data.foldLeft(Map.empty[Int, Double]) { (acc, item) =>
val currentScore = acc.getOrElse(item.customerId, 0.0)
val change = if (item.tx.isReturn) -item.tx.amount else item.tx.amount
acc + (item.customerId -> (currentScore + change))
}
}
This is much cleaner. I'm visiting every element exactly once, and I'm avoiding the overhead of creating intermediate grouped lists. I've moved from a "naive" solution to a "functional" solution, and finally to an "optimized" one. That's the trajectory you want to demonstrate in your assessment: show that you can get it working, then show that you know why the first way was suboptimal, and then provide the professional version.
📋 Practical Task
Exercise: Building a High-Frequency Trade Aggregator
You are tasked with creating a trade aggregator for a financial system. You are given a list of Trade objects, where each trade has a symbol (e.g., "AAPL"), a quantity, and a price. Some trades are 'Buy' and some are 'Sell'.
Requirements:
- Implement a function
calculateNetPosition(trades: List[Trade]). - The function must return a
Map[String, Double]where the key is the stock symbol and the value is the net quantity held (Buy increases quantity, Sell decreases it). - You must implement this using a
foldLeftto ensure the collection is traversed only once. - Do not use
groupBy, as the goal is to optimize for a high-volume stream of data.
case class Trade(symbol: String, quantity: Double, price: Double, side: Side)
sealed trait Side
case object Buy extends Side
case object Sell extends Side
// Your implementation here:
def calculateNetPosition(trades: List[Trade]): Map[String, Double] = {
???
}There are no comments for now.