Skip to main content

Programming in Scala using Scala CLI

· 10 min read
Ganesh Chand

For a programming language to be widely adopted, it must be beginner friendly.

Every master was once a beginner. Every pro was once an amateur. -- Robin Sharma

As a beginner to programming world, I am looking for a general purpose programming language that:

  • Requires minimal setup and gets me going
  • Is intuitive and easy to learn
  • Helps me avoid making obvious mistakes
  • Guides me with helpful and easy to understand error messages
  • Helps me build simple apps for fun without having to learn any build tools
  • Has welcoming and helpful user community
  • Has tons of free and paid resources
  • Provides me job opportunity

I think Scala checks most of those boxes but is it really a beginner friendly? The language itself is easy to learn but the pre-requisites to setup a learning and protyping environment can cause frustrations to begineers.

Common challenges for the beginners

Scala is primarily a JVM language. This means, as a beginner, I also need to learn installing Java Development Kit installed on my machine and oh! by the way, it should be compatible with the Scala version I am using. OMG! there are so many JDKs available. Which flavor of JDK should I use?

Scala official getting started guide recommends installing Scala using the installer tool coursier and use the SBT build tool to compile, run and test your program. For a beginner, that means spending hour(s) setting up a learning environment. You are also forced to learn the build tool which is really not required at all for beginners.

The language really should make it easier for beginners to get started with minimal steps and helps me stay engaged and motivated to learn more and grow my skills by applying the technique to solve interesting problems.

Enter scala-cli

Thanks to Scala Center and Virtuslab, we finally have scala-cli command line tool that really makes it super easy to start programming in Scala in minutes. As beginners, all you need to do is install scala-cli and you are ready to go.

  • It automatically installs Java and Scala and additional tools so you can just focus on learning the core language features.
  • It provides you both the Scala and ammonite REPLs for interactive learning and rapid prototyping.
  • It provides first-class support for scripting
  • It provides many other commands, as shown below. But you don't have to learn any of these commands to get started.

ganeshchand.com/blog

I would strongly recommend reading scala-cli documentation if you would like to explore all commands and features in details. My top 5 reasons why I love scala-cli and use it every day are:

  1. I am more productive: I don't have to worry about managing multiple Java and Scala versions on my computer. I can specify which Scala version and Java version to use either in my script or as command argument and let scala-cli figure out how to run it with the correct version. This also allows me to focus on the task at hand and quickly test my Scala code against different Scala and Java versions.

  2. I can easily share my Scala code/scripts to the community: Github Gists provide a simple way to share code snippets with others. Every gist is a Git repository, which means that it can be forked and cloned. scala-cli allows you to run the Scala code directly using the Gist URL. This incredibly simplifies especially in the open-source community how we report bugs and share a code that reproduces the bug.

  3. I can debug and build prototypes interactively and very quickly: I can quickly switch back and forth between the REPL and the code editor. I use REPL to explore the APIs and prototype my functions and expressions. Once I am happy with the prototype, I copy the code, get out of the REPL and add them to my scripts in the editor.

  4. I can use my favorite IDEs: IDEs help with auto-completion, code navigation and code refactoring. I use both IntelliJ and VSCode.

  5. I can create Jars and publish them locally and/or to artifactory: Without having any knowledge of build tool, I can convert my Scala script to an Open Source Scala Library by publishing it to Maven.

Getting Started with scala-cli

Now, let us see how Scala programming language, scala-cli tool, REPL and scripting all come together.

First, Install scala-cli on your machine.

# one command and that's all!
brew install Virtuslab/scala-cli/scala-cli

Next, verify if the installation was successful.

echo 'println("Hello")' | scala-cli -

Next, let's use the scala REPL to quickly experiment with our hello world program.

$ scala-cli console
Welcome to Scala 3.2.2 (11.0.18, Java OpenJDK 64-Bit Server VM).
Type in expressions for evaluation. Or try :help.


scala> println("Hello World, let us live in peace and harmony")
Hello World, let us live in peace and harmony

scala> :quit

Next, let's see how we can easily turn our above experiment into a Scala script that we can run from the command line.

Scala as a scripting language

Scala has a set of convenient constructs that help you get started quickly and let you program in a pleasantly concise style. Because of its expressiveness and conciseness with in-built type safety, it becomes an ideal scripting language.

The name Scala stands for scalable language." The language is so named because it was designed to grow with the demands of its users. You can apply Scala to a wide range of programming tasks, from writing small scripts to building large systems.

-Martin Odersky; Lex Spoon; Bill Venners; and Frank Sommers. Programming in Scala, Fifth Edition

Let's create a directory where we will create and edit our scripts. This is strictly not required but it's always better to stay organized.

mkdir  ~/learn_scala
cd ~/learn_scala

Now, we are in our ~/learn_scala directory. Let's create a hello world script.

# create a script that prints my message to the world
echo 'println("Hello World, let us live live in peace and harmony")' >> greetings.sc

# display the content of greetings.sc file
cat greetings.sc

println("Hello World, let us live live in peace and harmony")

Notice the above script looks exactly like a Python script. No ceremony is required.

Next, let's run this script.

scala-cli greetings.sc 
tip

When you run the scala-cli script first time, it will check your local environment and download and install the required libraries for you and therefore might take couple seconds . The subsequent execution should be super almost instantaneous!

scala-cli provides a run command to execute your program. But it's optional.

scala-cli run greetings.sc is same as scala-cli greetings.sc

Next, let's make this script executable. i.e. I should be able to run the script simply by by running the shell command: ./greetings.sc

First, add #! /usr/bin/env scala-cli to the top of the script. If you have scripted in python, you have probably seen #!/usr/bin/env python in your script.

The script should look like as shown below:

cat greetings.sc

#! /usr/bin/env scala-cli
println("Hello World, let us live live in peace and harmony")

Next, let's make this script executable by changing the file permission.

chmod +x greetings.sc

Now, you can run the script as ./greetings.sc You might ask why do I need ./ in the beginning and why can't I simply run it as greetings.sc? As answered here, dot-slash is a safety mechanism to indicate the program being executed is a user created command located in the current directory.

However, if you really really want to execute the script by simply typing greetings.sc, you can do so by adding your script directory to the $PATH environment variable as shown below:

export PATH="$HOME/learn_scala:$PATH"
greetings.sc

Hello World, let us live live in peace and harmony

You can take it even one step further by creating a command alias so you don't have to type the file extension. You can name it whatever you want as long as it doesn't conflict with existing commands.

alias hello="greetings.sc"
hello

Hello World, let us live live in peace and harmony

As I said earlier, you can share your script as Github Gist and rest of the world with scala-cli installed on their local machine can run your script using the Gist URL. Try running the below command:

scala-cli https://gist.github.com/ganeshchand/d2fbb4c03238329e0cd4b0019f373d25

Bonus content

The above script always prints "Hello World, let us live live in peace and harmony" no matter who runs it or when it runs. Real world scripts are parameterized to make them dynamic.

In our example, we should allow the end-users of our program to print their own message to the world.

With scala-cli scripts, command line arguments are accessed through the special args variable which is an array of strings. Users can provide space delimited strings as program arguments.

let's create a new script custom_greetings.sc that is parameterized on the message that needs to be printed. Also, let's customize the greeting based on what time of the day the script is run.

// content of the script custom_greetings.sc 

// greet with good morning or good afternoon or good evening based on the time of the day
val hour = java.time.LocalTime.now.getHour
val greeting = hour match {
case h if h < 12 => "Good Morning"
case h if h < 16 => "Good Afternoon"
case h if h < 20 => "Good Evening"
case _ => "Good Night"
}

val defaultMessage = "let us live live in peace and harmony"
val message = if(args.isEmpty) defaultMessage else args(0)
println(s"$greeting World, $message!")

Run this script from command line:

scala-cli custom_greetings.sc -- "Scala is fun"    
Good Afternoon World, Scala is fun!

Next, I am super excited about this cool command line tool I built and I would love to share with the larger community.

There are couple of ways to do it:

  1. Publish and share your script as github gist. Now, anyone can run your script by using the gist URL as shown below:
    scala-cli https://gist.github.com/ganeshchand/fa703cc5459aa92dd07210ea6d549765 -- "YOUR_MESSAGE"
  2. Publish your script in the public git repo and others can clone or download the script on their local machine and run it as shown below:
    scala-cli <LOCAL_PATH_TO_THE_SCRIPT> -- "YOUR_MESSAGE"
  3. Package your script as an executable jar or a scala library. You'd typically do this when you are building a real-world application or a utility library that typically requires you to organize your scripts as modules and provide a single entry point to your library or an application. Knowing how to package and distribute your code is not something as a beginner you are required to know. If you are comfortable using this feature, read here.

Closing Thoughts

scala-cli genuinely aims to simplify the developer experience for Scala users. As beginners, you can now focus on learning the core language constructs, programming concepts and solve real world problems without the distraction of build tools and environment setup. I am sure the tool will mature even more over time. In the upcoming blog in #scala-cli series, I will talk about using external libraries in your scripts and write a script to solve a real world problem. Stay tuned!

If you have any feedback or comments for me on this blog, please feel free to reach out to me on LinkedIn or Twitter.