The Scala Toolkit

Tuesday 20 June 2023

Adrien Piquerez (Scala Center), Szymon Rodziewicz (VirtusLab)

The Scala organization is pleased to announce the release of the Scala Toolkit and its series of tutorials in docs.scala-lang.org/toolkit. The current version is 0.2.0. We call it an early release because it is not 1.0.0 yet (see below in the FAQ for more details).

The Toolkit is a bundle of libraries from the ecosystem that work well together to perform common programming tasks. It is a good fit for trying out Scala, writing a script, prototyping, or bootstrapping a new application. It can also be used in larger applications.

In this initial release, the Toolkit includes OS-Lib for working with files and processes, UPickle for parsing JSON, sttp for sending HTTP requests, and MUnit for unit testing.

You can try out the Toolkit using Scala CLI:

  • In the REPL
    $ scala-cli --toolkit latest
    
  • In a Scala script or file
    //> using toolkit latest
    

This blog post outlines the motivation and design of the Toolkit. It illustrates how to use it, including setup instructions for tools such as Scala CLI, sbt, Mill, and Maven. Finally, a FAQ section contains answers to commonly asked questions.

Acknowledgements

We would like to express our gratitude and appreciation to the authors and maintainers of com-lihaoyi/os-lib, com-lihaoyi/upickle, softwaremill/sttp and scalameta/munit. Their collaborative efforts and dedication have been crucial in the successful creation of the Toolkit. We are looking forward to continued collaboration in the future.

Why the Toolkit?

The Toolkit project is a significant step in our ongoing effort to make Scala more accessible, lightweight, and fun to use. In particular, we aim at lowering the onboarding barrier for newcomers from different programming backgrounds.

Scala’s library ecosystem offers multiple choices for doing almost anything. The ecosystem’s richness is a great strength of the language, but can also be confusing and intimidating. The Toolkit aims to offer default choices for coders who aren’t in a position to evaluate competing libraries and just want to get something done.

What is the Toolkit?

The Toolkit gathers a number of pre-existing libraries of the ecosystem that focus on concrete, recurring software engineering problems, such as working with files and processes, parsing JSON, and sending HTTP requests.

Its documentation can be found at docs.scala-lang.org/toolkit. It comprises a collection of concise tutorials, including short code examples, that aim at being self-contained. They not only explain how to use each library individually, but also how to combine them in meaningful ways.

The Toolkit aims at being approachable. It does not require extended knowledge of the more advanced features of Scala (higher-kinded types, macros, etc) nor of the more advanced concepts of the ecosystem (asynchronous, pure-functional, reactive, actor-based).

The Toolkit favors libraries that provide a user-friendly getting-started experience. They enable the developer to explore the API with auto-completion and integrated documentation (scaladoc), and discover the functionalities as they write their code. Additionally, they prioritize clear and informative types, signatures and error messages, rather than abstraction and flexibility.

What can you do with the Toolkit?

Here is an example of what you can do with the Toolkit:

//> using toolkit 0.2.0

import sttp.client4.quick.*

val json = ujson.Obj(
  "location" -> "hometown",
  "bio" -> "Scala programmer"
)

val token = sys.env("GITHUB_TOKEN")

val response = quickRequest
  .patch(uri"https://api.github.com/user")
  .auth.bearer(token)
  .header("Content-Type", "application/json")
  .body(ujson.write(json))
  .send()

println(response.code)
// prints: 200

This short program sends an HTTP request to the Github REST API, to update the profile of the authenticated users. In a few lines, it shows:

  • how to construct a JSON object, with ujson.Obj
  • how to read an environment variable, with sys.env
  • how to create an HTTP request, with the quickRequest builder in sttp
  • how to authenticate the request with a token
  • how to add a JSON body and a header
  • how to send the request and receive a response

More examples can be found in docs.scala-lang.org/toolkit.

When to use the Toolkit?

The Toolkit is a good fit for trying out Scala, writing a script, prototyping, or bootstrapping a new application. It can also be used in larger applications.

Trying out Scala

The Toolkit offers accessible APIs that should feel familiar to programmers coming from different backgrounds, such as Java or Python. It is a good resource for learning or teaching how to use Scala in real-world applications, giving newcomers the opportunity to be productive early in their Scala learning journey.

Scripting and prototyping

The Toolkit tutorials encourage synchronous code that throws exceptions instead of returning errors as values. This is particularly well-suited for scripting and prototyping purposes, where you want to obtain results quickly, without caring much about safety or performance.

Toolkit libraries do have the capability to handle errors as values and support asynchronous operations, but these features are optional and can be enabled when required.

Bootstrapping an application

When bootstrapping an application, selecting libraries from the available ecosystems, familiarizing yourself with them, and configuring them appropriately is challenging and time consuming.

The toolkit aims at reducing this overhead, by offering a comprehensive set of pre-packaged libraries that cater to many of your needs. These features are documented in a centralized location, allowing for easy reference.

Additionally, the Toolkit minimizes transitive dependencies, to help you steer clear of dependency hell.

How to get the Toolkit?

Using Scala CLI

In a terminal, you can start the REPL with the Toolkit on the classpath.

$ scala-cli --toolkit 0.2.0

Or you can get it in a Scala script or file.

//> using toolkit 0.2.0

val json = ujson.read("""{"message": "Hello, World!"}""")
println(json("message"))
// prints: Hello, World!

In build tools

The toolkit has two artifacts: one for the main target and another for the tests.

libraryDependencies ++= Seq(
  "org.scala-lang" %% "toolkit" % "0.2.0",
  "org.scala-lang" %% "toolkit-test" % "0.2.0" % Test
)

In the main module:

def ivyDeps =
  Agg(
    ivy"org.scala-lang::toolkit:0.2.0"
  )

In the test module:

def ivyDeps =
  Agg(
    ivy"org.scala-lang::toolkit-test:0.2.0"
  )
<dependency>
  <groupId>org.scala-lang</groupId>
  <artifactId>toolkit</artifactId>
  <version>0.2.0</version>
</dependency>
<dependency>
  <groupId>org.scala-lang</groupId>
  <artifactId>toolkit-test</artifactId>
  <version>0.2.0</version>
  <scope>test</scope>
</dependency>

FAQ

What is the difference between the Standard Library and the Toolkit?

The Scala Standard Library contains the most essential building blocks to build and run Scala programs, such as collections. It also contains the Scala runtime, without which you cannot run any Scala program.

The Toolkit, in turn, relies on the Standard Library as a dependency and expands upon it by addressing specific use cases. When developing a Scala program, you have the flexibility to choose between utilizing the Toolkit or leveraging other libraries.

How are the libraries selected?

To select the libraries of the Toolkit we used the following criterion:

  • API Usability: Consistency, abstraction level, visibility, language level etc.
  • Responsiveness and availability of the maintainers
  • Documentation
  • Popularity
  • Dependencies
  • Support for Scala.js and Scala Native

Who owns the Toolkit libraries?

The Toolkit is composed of pre-existing libraries from the ecosystem, created by different organizations and individuals.

Those libraries are owned by their respective authors and maintainers. The Scala organization takes on the responsibility of curating the libraries, releasing the Toolkit artifacts and regularly updating the tutorials in docs.scala-lang.org/toolkit.

The Scala organization can provide some guidance or temporary help to ensure smooth integration and compatibility of the Toolkit libraries.

What does early mean in early release?

The Toolkit version is said to be early as long as it begins with 0.x, as in 0.2.0. It allows for the API of the Toolkit to evolve and change without any restriction. This is in part due to the fact it depends on milestone versions of sttp, and MUnit.

Once the Toolkit reaches its first stable version, it will be labeled as 1.0.0. Only stable versions of libraries will be included.

What is the versioning scheme of the Toolkit?

The Scala Toolkit follows the semantic versioning scheme, provided that the underlying libraries also adhere to the semantic versioning scheme.

A new patch version of the Toolkit signifies that there have been only patch bumps of the underlying libraries. A new minor version of the Toolkit includes minor bumps of the underlying libraries, but avoids any major bump. A new major version of the Toolkit includes at least one major bump of an underlying library.

Does it support Scala 2 and Scala 3?

You can use the Toolkit with Scala 2.13 and Scala 3.x.

Does it support Scala.js and Scala Native?

All the versions of the Toolkit will support Scala.js and Scala Native, with some differences in the provided functionalities.

At the moment, there is no support for files and processes in Scala.js, mainly because such functionalities would heavily depend on your JavaScript runtime.

You should be able to develop your script using the JVM toolchain, but then you can switch to Scala Native to get instant startup, or to Scala.js to deploy and run your script in web browsers.

Can there be other Toolkits?

Yes, there is room in the Scala ecosystem for other “toolkits” besides the Scala Toolkit. For example, the Typelevel Toolkit is the toolkit of the Typelevel organization.

Typelevel is an open-source organization that builds and maintains a purely functional stack of libraries in Scala, based on cats.

Their toolkit is composed of Typelevel libraries and fully supports JVM, Node.js, and Native. You can try it out in Scala CLI:

//> using toolkit typelevel:latest

import cats.effect.*

object Hello extends IOApp.Simple:
  def run = IO.println("Hello, world!")

Whether you should use the Scala Toolkit or the Typelevel Toolkit depends on your preference and familiarity with pure functional programming.

How to share feedback?

To share general feedback about the Toolkit you can read and comment on this thread in the Scala Users forum.

To report an issue you can go to the issue tracker in the scala/toolkit repository.

Plans for the future

We are focused on stabilizing the initial release of the Toolkit, to ensure the first set of features is functioning seamlessly.

Simultaneously, we are laying the ground for future versions, in which we will expand the Toolkit’s capabilities. Among the functionalities under consideration, we are exploring manipulation of CSV files, SQL database querying, HTTP servers, and logging.

Our goal is to create a versatile Toolkit that caters to a wide range of software engineering needs, with a particular emphasis on supporting newcomers, scripting, and prototyping.