Photo by Bill Oxford on Unsplash

Developers often need to write some code snippets to check ideas or help their colleagues. Scala offers a powerful REPL that allows running such quick samples. Here are some ideas how can you make it much smoother to use.

Get Ammonite

This is the first thing you should do. Go to this link and install the REPL for your Scala version (Scala 2.12 recommended for examples below, because some libraries haven’t been yet released for Scala 2.13).

http://ammonite.io/#OlderScalaVersions

Configure Ammonite predef file to preload common dependencies

Ammonite can load a predefined script on startup. This is an excellent feature, allowing you to initialize dependencies or some utils. Here’s an example predef.sc file which can be put in ~/.ammonite/:

import $ivy.`org.typelevel::cats-core:2.0.0`, cats._, cats.implicits._
import $ivy.`io.monix::monix:3.0.0`
import $ivy.`dev.zio::zio:1.0.0-RC12-1`
import $ivy.`org.typelevel::cats-effect:1.3.1`
import $ivy.`org.scalatest::scalatest:3.0.8`,org.scalatest._
import $ivy.`org.scalacheck::scalacheck:1.14.0`
import $ivy.`com.github.chocpanda::scalacheck-magnolia:0.2.2`
import $ivy.`io.chrisdavenport::cats-scalacheck:0.2.0-M1`
import scala.concurrent.ExecutionContext.Implicits.global
import scala.concurrent.duration._
import scala.concurrent.Future
import scala.util.{Failure, Success}
import scala.concurrent.Await
import org.scalacheck.{Arbitrary, Gen}
import org.scalacheck.magnolia._
def randomObj[T: Arbitrary] = implicitly[Arbitrary[T]].arbitrary.sample.get

Current version of my predef file is available on GitHub.

Let’s see what we’ve got here:

  • Cats, ZIO, Monix -> for fiddling with effects and using functional programming abstractions
  • Scalatest, scalacheck, scalacheck-magnolia -> for assertions and random generators. With scalacheck-magnolia and the randomObj util defined in the script, you can instantly create instances of case classes, even complex nested ones.
@ case class User(name: String, age: Int, address: String)
redefined class User
@ randomObj[User]
res1: User = User(
“\u3bd2\ua185\ue0d0”,
639667659,
“\u3ed4\uc8e7\u3daf\ub31d\u7f25\ud710\u8912\uc3bd\u6db3\uba55\ubd05\u4838\uf713\u4d1e\u3802\u7d83\uae6f\u3d6c\ub5e5\u5a08\u7d4a\ua574\ua90b\u8dee\u82d2\ub604\u01a9\u9e15\u18d8\u70d0\u579d\u4cf3\u7b0a”
)
  • Some imports for useful common types
  • The global Execution Context for all Future-related operations

Now all you need is to run amm in your terminal and start power-coding!

Alternatives

Be sure to check Scala Fiddle — it’s a web tool for similar purposes, and it has a nice set of libraries that you can quickly include.

It is possible to use Ammonite REPL from sbt console. If you decide to do so, you’ll be able to use all the dependencies available in your project, as well as project classes. However, this approach requires some manual intervention into the build.sbt file and the project has to be compiling.

There are also IntelliJ IDEA Worksheets which are now integrated with Ammonite, also requiring build.sbt intervention:
https://www.jetbrains.com/help/idea/work-with-scala-worksheet-and-ammonite.html

What’s next?

Do you have any ideas how a REPL flow can be further improved? Or maybe you have some suggestions what else can be added to the predef file? Please leave a comment!