Scastie provides an easy start for learning Scala

Photo by Lucas Davies on Unsplash

Scala is said to be a very difficult computer programming language to learn. Maybe it’s because it’s a functional/object-oriented hybrid, and because it’s not available right in your Web browser offline.

Well, given that JavaScript is a rather slapdash haphazard functional/object-oriented hybrid, the first excuse goes right out the window.

As for the second excuse, if you have an Internet connection and a Web browser (which you probably do if you’re reading this), then you have access to Scastie, an online Scala REPL.

Sure there are online REPLs for Java, C++, C#, etc., but to the best of my knowledge, none of them are official. Scastie is.

If you already have IntelliJ on your computer, it would make sense to have IntelliJ download the Scala for IntelliJ plugin.

But if you don’t have IntelliJ and don’t want to download and install anything new on your computer, using Scastie in your Web browser might be an excellent option for exploring Scala without making any serious commitment of your computer’s resources.

I do have to admit that I was not a complete beginner when I started learning Scala. I knew Java, and I slowly realized that I also knew a little bit about functional programming already, thanks to Wolfram Mathematica.

For the rest of this article, I will assume that you already know Java. You might also know the “Wolfram Language,” but I won’t assume that you know that.

So this article is not for complete beginners. However, if you know C++ or C# but not Java, you can probably still follow along. And if you know JavaScript but not Java (the two are a lot less alike than the names suggest), you might find some things strangely familiar.

Let’s get started. In a separate tab or window on your Web browser, open Scastie, either by using the link given above or by typing scastie.scala-lang.org in your browser’s address bar.

Mostly I’ve used Firefox. I can tell you that Scastie also works in Chrome and Opera. I believe it works in Edge, I doubt it works in Internet Explorer.

[NOTE: Scastie has changed since I first wrote this. The basic idea remains the same, but many important details have changed. Rather than rewrite this article each time I notice a change, I will write a separate article and append a link at the end of this article.]

The first time you go to the Scastie website, you should see a “Welcome to Scastie” message that lists five things you can do:

  • Run / Edit

Dismiss the welcome message and you will probably see this in the main editor area:

List("Hello", "World").mkString("", ", ", "!")

Click “Run”. If everything is in order, the following non-editable text will appear in the editor area right after the source:

Hello, World!: java.lang.String

Here’s something that will look a lot more familiar to Java programmers. Go ahead and type this in the editor area, either after the previous line or replacing the previous line:

System.out.println("Hello, world!")

Except for the missing semicolon, that looks just like Java. And maybe you even did type the semicolon into Scastie, and that’s fine. Click “Run.” The console should now appear.

You might see a bunch of lines scrolling by, letting you know that Scastie is retrieving various packages. Or you might not. Either way, you should eventually see this in the console:

Hello, world!

I feel kinda bad making Scastie put all this effort just to print a couple of words to the console. Scastie wraps the println statement into a Main, invokes the server-side Scala Build Tool, runs Main and displays the results in your Web browser.

Now let’s do something just a little bit more involved. Do you remember the Euclidean GCD algorithm from high school math?

In a nutshell, to figure out gcd(a, b), you need to solve a = qb + r so that f(r) < f(b). Then reset a to b, b to r and repeat until you get r = 0.

  def euclideanGCD(a: Long, b: Long): Long = {
var currA, currB, currRemainder = 0L
if (Math.abs(a) < Math.abs(b)) {
currA = Math.abs(b)
currB = Math.abs(a)
} else {
currA = Math.abs(a)
currB = Math.abs(b)
}
while (currB != 0) {
currRemainder = currA % currB
currA = currB
currB = currRemainder
}
currA
}
(1 to 100).map(euclideanGCD(_, 12))

This is starting to look less Java-like, but a lot of the elements are still recognizable.

Instead of giving the data type first and then the name of the function parameter (e.g., “long a, long b”) the name of the function parameter goes first, then the data type (hence “a: Long, b: Long”).

We could say that these 64-bit longs are primitives like in Java, but that would be misleading. For now suffice it to say that these are not object wrappers; this is a point I’ll come back to later.

The return type of the function needs to be declared, but logically in Scala it follows the list of parameters rather than preceding the function name like in Java.

This is very important: note the equal sign before the function’s opening curly brace. IntelliJ helps you out with details like these, Scastie might not.

Scala can infer type if you give it good hints in a var statement. There probably are some nightmare scenarios, but nothing like the nightmare scenarios in JavaScript.

Since we’re initializing currRemainder to 0L, we don’t need to explicitly declare it as Long. This is not really a big deal, given that apparently now Java also has var (not sure if it was introduced in Java 9 or in Java 10).

The if statement and the while statement are just like in Java, except for the omission of the semicolons. Of course you can put in semicolons if you want to.

The last line before the function’s closing curly brace marks a more significant departure from Java. Using the keyword return at this point is strongly discouraged.

Scala understands the last statement of the function as being the value of the function as a whole. As long as the data type of currA matches the data type of euclideanGCD(), the Scala compiler will not have any trouble with that line.

The return keyword is also unnecessary in an if-else when it’s clear that both branches deliver a result of suitable type.

The line after the euclideanGCD() function is a lot to unpack, so I will reiterate it now:

  (1 to 100).map(euclideanGCD(_, 12))

First, (1 to 100) creates an object, specifically, a collection. This collection consists of 32-bit integers, starting with 1 and going in order up to 100.

Well, technically this Range object only holds the starting 1, the ending 100 and the step of 1, but it doesn’t really hurt us to think of it as if it really did hold every integer from 1 to 100.

In Scala, everything is an object: primitives are objects, objects are objects, and functions are objects. The Int “primitive” is an object, so 1 is an object and you can call the to() “method” on it:

1.to(100)

This creates an immutable Range object, which you can verify consists of 100 elements:

1.to(100).length

And since Scala allows you use infix notation in cases like this, you can write 1 to 100 instead of 1.to(100).

For the most part in Scala, you don’t need to worry about the distinction between primitives like int and long and object wrappers like Integer and Long; the Scala compiler will take care of any necessary conversions.

Next, I would like to apply the euclideanGCD function to each number n in the Range object we just created to see what gcd(n, 12) is for each n. In Java we might have to use a for loop. Or maybe a for-each loop.

Here’s where the functional paradigm really shines. In Scala, we can just map the elements of the Range to any function of suitable type, using, of course, map:

  (1 to 100).map(euclideanGCD(_, 12))

It’s not even necessary to name an iterator variable like you would in a Java for-each loop. Since Scala can infer the necessary type in cases like these, we can just use the wildcard character _.

Click “Run.” Scastie wraps this into a Main, uses the server-side Scala Build Tool, runs Main and delivers the results:

Vector(1, 2, 3, 4, 1, 6, 1, 4, 3, 2, 1, 12, 1, 2, 3, 4, 1, 6, 1, 4, 3, 2, 1, 12, 1, 2, 3, 4, 1, 6, 1, 4, 3, 2, 1, 12, 1, 2, 3, 4, 1, 6, 1, 4, 3, 2, 1, 12, 1, 2, 3, 4, 1, 6, 1, 4, 3, 2, 1, 12, 1, 2, 3, 4, 1, 6, 1, 4, 3, 2, 1, 12, 1, 2, 3, 4, 1, 6, 1, 4, 3, 2, 1, 12, 1, 2, 3, 4, 1, 6, 1, 4, 3, 2, 1, 12, 1, 2, 3, 4): scala.collection.immutable.IndexedSeq

Another task that functional programming makes easier is picking out elements of a collection that meet a certain criterion. You just need filter() and an appropriate Boolean function.

For this next example, you may delete the line with map if you like, but be sure to keep euclideanGCD(). I would like a list of all positive integers less than or equal to 100 with no prime factors in common with 12.

(1 to 100).filter(euclideanGCD(_, 12) == 1)

The result should include all the prime numbers from 5 to 97, and composite numbers like 25, 91.

Vector(1, 5, 7, 11, 13, 17, 19, 23, 25, 29, 31, 35, 37, 41, 43, 47, 49, 53, 55, 59, 61, 65, 67, 71, 73, 77, 79, 83, 85, 89, 91, 95, 97): scala.collection.immutable.IndexedSeq

Maybe at this point it’s not obvious that we’re passing functions around as parameters. In Scala, a function can be passed to another function and it can be passed to a constructor, which is, after all, a special kind of function. This next example will make that point a lot more obvious.

Usually, the function f(n) in the Euclidean GCD algorithm is the absolute value function; it’s the most obvious and practical choice when we’re just dealing with “regular” integers.

But it’s not the only possible choice. We could just as easily use f(n) = n², to name just one example. The limitations are practical rather than theoretical.

So we want to rewrite euclideanGCD() so that it takes in two integers and some function that we specify at runtime.

Since it’s possible that euclideanGCD() could be passed a function that’s unsuitable for the Euclidean algorithm, we’ll also need to create an exception to throw when that happens.

For this next exercise it might be a good idea to clear out everything you’ve typed into Scastie so far.

First, the exception.

class NonEuclideanDomainException(exceptionMessage: String, a: Long,
b: Long, eucFn: Long => Long)
extends Exception(exceptionMessage: String) {
val causingA = a
val causingB = b
val causingFn = eucFn
}

Note that the primary constructor is “fused” with the class declaration. To construct a NonEuclideanDomainException, you need an exception message in a String, two 64-bit integers and a function that operates on a single 64-bit integer to give another 64-bit integer.

The exception message is passed along to the Exception constructor. We don’t need to write super(exceptionMessage), Scala takes care of that for us.

Technically there are no checked exceptions in Scala, so it makes little difference whether we subclass NonEuclideanDomainException from Exception or RuntimeException.

If this was to interact with Java classes that you write, you might want to give some more thought to these subtleties. But, since as far as I know, Scastie can’t handle Java code that you write, the point is moot for this exercise.

The two 64-bit integers and the function are put into fields declared with val, so Scala will generate getters but not setters.

Now, here’s our rewritten Euclidean GCD function. Paste this into the Scastie editor area after the closing curly brace of the NonEuclideanDomainException class definition.

  def euclideanGCD(a: Long, b: Long, eucFn: Long => Long): Long = {
var currA = Math.abs(a)
var currB = Math.abs(b)
var currRemainder = 0L
if (eucFn(currA) < eucFn(currB)) {
currA = Math.abs(b)
currB = Math.abs(a)
}
while (eucFn(currB) != 0) {
currRemainder = currA % currB
if (eucFn(currA) < 0 || eucFn(currB) < 0 ||
eucFn(currRemainder) < 0) {
val excMsg = "The function " + eucFn.getClass.getName +
" is not a valid Euclidean function because it
sometimes returns negative values."
throw new IllegalArgumentException(excMsg)
}
if (eucFn(currRemainder) >= eucFn(currB)) {
val excMsg = "Z is not Euclidean for the function f = " +
eucFn.getClass.getName + " since f(" +
currRemainder + ") = " + eucFn(currRemainder)
+ " but f(" + currB + ") = " + eucFn(currB) +
"."
throw new NonEuclideanDomainException(excMsg, a, b, eucFn)
}
currA = currB
currB = currRemainder
}
currA
}

Scastie will have no problem with idiosyncratic line breaks except when they break up the initialization of a String, so you will need to edit the two val excMsg statements so that each is on its own line.

This version of euclideanGCD still uses Math.abs() to make sure we don’t need to multiply anything by −1 at the end. Other than that, it will use the passed function eucFn(), which may or may not be Math.abs().

Next, we need an improper Euclidean function and a pair of numbers to try it on.

def negCube(n: Long): Long = n * n * -neuclideanGCD(-27, 18, negCube)

Run it. The console should fill up with error messages. Buried somewhere in there you should see a message saying negCube() is not a valid Euclidean function.

scastie: Sending task to the server.
scastie: Connected. Waiting for sbt
sbt: [info] Compiling 1 Scala source to /tmp/scastie8145071749968837443/target/scala-2.12/classes...
sbt: [info] Running Main
sbt: [error] (run-main-27) java.lang.ExceptionInInitializerError
...omitting a few lines...
at java.lang.reflect.Method.invoke(Method.java:498)
Caused by: java.lang.IllegalArgumentException: The function Playground$$Lambda$4732/440283381 is not a valid Euclidean function because it sometimes returns negative values.
at Playground.euclideanGCD(main.scala:28)

at Playground.<init>(main.scala:51)
at Main$.<init>(main.scala:54)
at Main$.<clinit>(main.scala)
at Main.main(main.scala)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
...omitting a few more lines...
[trace] Stack trace suppressed: run 'last compile:run' for the full output.
sbt: [error] (compile:run) Nonzero exit code: 1
scastie: Closed.

Let’s try another invalid function.

  def invalidFunctionF(n: Long): Long = 10L

Amend the Euclidean GCD line to use this new invalid function.

  euclideanGCD(-27, 18, invalidFunctionF)

Run it. Somewhere in the console, you should find something like this:

at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
Caused by: Playground$NonEuclideanDomainException: Z is not Euclidean for the function f = Playground$$Lambda$8507/923259725 since f(9) = 10 but f(18) = 10.
at Playground.euclideanGCD(main.scala:35)
at Playground.<init>(main.scala:55)
at Main$.<init>(main.scala:58)
at Main$.<clinit>(main.scala)
at Main.main(main.scala)

Now, define a squaring function.

  def square(n: Long): Long = n * n

You may either delete negCube() and invalidFunctionF() or leave them in there. But do amend the line for gcd(−27, 18) to use square() instead of negCube() or invalidFunctionF().

  euclideanGCD(-27, 18, square)

Run it now, you should get the right result:

9: Long

Of course it’s possible to define functions such that euclideanGCD() won’t trigger any exceptions but nonetheless delivers incorrect results.

And of course it’s also possible for a function that is theoretically valid to trigger exceptions in an implementation with practical limits, like the 32- or 64-bit limits for signed integers.

As far as I know, you can’t use JUnit in Scastie, but you can definitely use JUnit to test Scala source in IntelliJ, and presumably also NetBeans and Eclipse. However, you can access Scalatest through Scastie’s Build Settings.

With Scastie, you can save your programs for later use. Also, depending on your Web browser settings and your Internet connection, you might find that Scastie retrieves the program you were working on in your previous browsing session.

I hope that reading this and trying out Scastie convinces you to explore Scala further.

One possible next step, if you find Scastie too limiting, would be to download and install the Scala binaries on your system (you also need to have the Java JDK). These include the command line Scala compiler and a Scala REPL that you can use locally.

Or, like I mentioned, if you have IntelliJ, you can simply have it download and install the Scala for IntelliJ plugin. Configuring NetBeans for Scala is a lot more involved, and I have not actually done it yet, so I shouldn’t say anything more about that for now.

There are other Scala tutorials here on Medium, some more elementary than others, like the 10-minute introduction by Teiva Harsanyi. Well, that one starts out elementary but quickly ramps up to advanced concepts like currying and closures.

I also recommend the book Scala for the Impatient by Cay Horstmann. Scastie might be sufficient for the early chapters of that book, though you might find the Scala REPL on your local system a better option as you get more familiar with Scala.

Scastie has changed since I first wrote this article. The most important change, in my opinion, is that it now provides URLs so that you can revisit snippets and share them. I wrote an article about this change and other changes, like that now the Run button is called “Save.”

is a composer and photographer from Detroit, Michigan. He has been working on a Java program to display certain mathematical diagrams.