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
179: Scala Scripting with Scala-CLI
By now, you're probably used to the ritual of creating a full sbt project: the build.sbt, the nested folder structure, and the long wait for the first compile. It's great for enterprise apps, but it's a nightmare when you just want to write a 50-line script to automate a task or poke at an API. That's where Scala-CLI comes in. It treats Scala more like Python or Ruby, letting you run a single file while still keeping the power of the JVM.
Ditching the sbt overhead
I've got a recurring need to check the star count of a few GitHub repositories to track some libraries I'm eyeing. Instead of a full project, I'm just going to create a file called stars.scala. One of the best things about Scala-CLI is that we can skip the object Main extends App boilerplate and just write code at the top level.
// stars.scala
val repo = "typelevel/cats-effect"
println(s"Fetching stars for $repo...")
// I'll add the actual HTTP logic in a second
To run this, I just hit scala-cli run stars.scala in my terminal. It's nearly instantaneous because there's no heavy project initialization happening behind the scenes.
Adding libraries without a build file
Now, I need to actually hit the GitHub API. I don't want to write raw Java HttpURLConnection code—that's a miserable experience. I'll use sttp for the request and upickle for the JSON parsing. Normally, this would mean editing a build.sbt file. With Scala-CLI, I use "using" directives right at the top of the file.
//> using dep "com.softwaremill.sttp.client3::core"
//> using dep "com.lihaoyi::upickle::scala_2.13"
import sttp.client3._
import upickle.default._
val repo = "typelevel/cats-effect"
val backend = HttpClientSyncBackend()
val response = basicRequest
.get(s"https://api.github.com/repos/$repo")
.header("User-Agent", "Scala-CLI-Script")
.send(backend)
println(response.body)
The //> using dep lines are the magic here. Scala-CLI reads these comments, fetches the dependencies from Maven Central, and handles the classpath for you automatically.
Oops, I missed a dependency
I wanted to parse the JSON to get just the stargazers_count field, so I tried to define a case class and use read`json`. I wrote the code, hit run, and immediately got a ClassNotFoundException. I realized I had added the core upickle dependency, but I forgot that for certain Scala versions or specific JSON features, I might need the companion library or a specific Scala version suffix.
Actually, looking closer, I had a typo in my dependency string—I used a colon where there should have been a double-colon for the Scala version mapping. It's a small mistake, but it's a classic "scripting" moment where you're moving faster than you're thinking. I fixed it to "com.lihaoyi::upickle::scala_2.13", and suddenly everything clicked into place.
Polishing the tool
To make this actually useful, I don't want to hardcode the repo name. I'll use args, which Scala-CLI provides as a built-in array of strings containing the command-line arguments.
//> using dep "com.softwaremill.sttp.client3::core"
//> using dep "com.lihaoyi::upickle::scala_2.13"
import sttp.client3._
import upickle.default._
if (args.isEmpty) {
println("Please provide a repo name (e.g., 'owner/repo')")
System.exit(1)
}
val repo = args(0)
val backend = HttpClientSyncBackend()
val response = basicRequest
.get(s"https://api.github.com/repos/$repo")
.header("User-Agent", "Scala-CLI-Script")
.send(backend)
response.body match {
case Some(body) =>
val json = ujson.read(body)
val stars = json("stargazers_count").num
println(s"The repo $repo has $stars stars!")
case None =>
println("Failed to fetch data.")
}
Now I can run scala-cli run stars.scala "scala/scala3" and get an immediate answer. If I want to distribute this to a teammate, I don't have to give them a whole git repo; I just send them this one file. They run it with Scala-CLI, and the dependencies are resolved automatically based on those //> using directives.
📋 Practical Task
Build a Currency Conversion Script
Your task is to create a Scala-CLI script named convert.scala that fetches the current exchange rate between two currencies and converts a given amount.
- Use the free
https://open.er-api.com/v6/latest/USDAPI (or a similar public currency API) to get current rates. - Use
//> using depto includesttpfor the HTTP request andupicklefor JSON parsing. - The script should accept three command-line arguments:
amount,fromCurrency, andtoCurrency(e.g.,scala-cli run convert.scala 100 USD EUR). - The script should output the converted amount formatted to two decimal places.
- Ensure you handle the case where the user provides an incorrect number of arguments by printing a helpful usage message.
There are no comments for now.