Using the Scala REPL as a makeshift Java REPL

A little bit of a run of the Scala REPL with one of my Java JARs loaded in.

As you might already know, REPL stands for Read Evaluate Print Loop. It’s a way to try out things in a computer programming language on the command line and see immediate results.

You might also already know that Java is a programming language for the Java Virtual Machine (JVM), which can theoretically run on any computer, and that Scala is also a programming language for the JVM.

And that for a long time, Java did not really have a REPL, but Scala did, almost from its very beginning in 2006. And you can use the Scala REPL to run subroutines you’ve written in Java.

I know that there have been Java REPLs online for years. I have used one of them a few times, and another one once or twice. I am also aware of JShell, which was introduced with Java 9 (for now I lag behind with Java 8).

If you don’t feel like upgrading to Java 9 just yet (there are still legitimate reasons for that feeling), you can just use the Scala REPL.

Since Scala has access to pretty much everything in java.lang, the Scala REPL would be a bona fide Java REPL if it weren’t that you have to use Scala syntax rather than Java syntax.

And you can load in a JAR that was compiled from Java source code and then you have access to anything that was declared public therein. To my knowledge, no online Java REPL can do that.

Using the Scala REPL as a makeshift Java REPL might seem like the sort of solution that I should e-mail to 2008, when people would have cared about it.

However, using the Scala REPL for Java might actually be superior to JShell in some ways. For one thing, overloaded operators can be a major convenience.

As I learn more about Scala, the Scala REPL will become even more useful to me as a Java REPL.

Before I get to that, though, I should address why anyone who uses a unit testing framework like JUnit would have any need or want for a REPL.

After all, the reason I started using JUnit in the first place was because I realized that the very primitive and limited REPLs I had built into my biggest Java project at the time (a program that draws diagrams of prime numbers in imaginary quadratic integer rings) were inadequate for testing the various “moving parts” of the program.

With JUnit, I can write a test that checks, for example, my Legendre symbol implementation against a thousand pairs of prime numbers in a matter of seconds.

To run all the tests in my project should only take a minute, two at the most. That would take forever on a REPL, or even on a primitive test suite without assertions.

The thing, though, is: how do I know what needs to be tested and how to test it? One way is by trying things on a REPL.

I might not be able to test a thousand pairs of prime numbers at a REPL in a reasonable amount of time if I have to input them one at a time, but I can think of specific pairs of prime numbers that might be troublesome for my program but which I didn’t think to test for when writing my unit tests.

On the REPL, I can try one specific case of a given scenario, and if I see it doesn’t give me the result I expect, I write a test for several cases of that given scenario, have that test fail and then I get to work on fixing the program so it passes the test.

Take for instance the Euclidean greatest common divisor (GCD) algorithm. In the domain of Z, the familiar integers we all know so well, …, −3, −2, −1, 0, 1, 2, 3, …, it is easy to know what to test for in an implementation of the Euclidean GCD.

As usual, I’m not going to get too in depth on the math here. If you’re curious about the mathematical aspect of it, you should be able to find more information in elementary number theory books, on Wolfram MathWorld and in the OEIS.

So, to test an implementation of the Euclidean GCD in Z, you’ll want to test that pairs of consecutive integers have a GCD of 1, and the same goes for pairs of consecutive odd integers.

Pairs of consecutive Fibonacci numbers (e.g., 21 and 34, 34 and 55) should also be identified as coprime. Pairs of consecutive even integers should have a GCD of 2.

If your GCD implementation gives results different than these, then you know your implementation has a problem. Here’s one unit test I would write:

How do I test that euclideanGCD(a, b) works correctly in, say, Z[i]? Or how about Z[ √−2]?

The only things I was sure about at the beginning is that euclideanGCD(a, b) should throw an exception if a and b are from different domains, and another exception if both a and b are from the same non-Euclidean domain, like the famous Z[ √−5].

I can certainly write tests for exceptions, whether with annotations or with a good old-fashioned try-fail-catch.

But to figure out tests for the normal functioning of euclideanGCD(a, b) with a and b both integers from the same Euclidean imaginary quadratic ring, I needed a REPL in which to try out different kinds of pairs.

And so it was thanks to the Scala REPL that I discovered that my implementation of the Euclidean GCD algorithm seemed to give the right result for gcd(−3/2 + (√−7)/2, 8) but would crash when asked to compute gcd(−3/2 + (√−7)/2, 10).

The latter computation would cause an ArrayIndexOutOfBoundsException, which led me to find that I had made a mistake with the checking of norms when a is not divisible by b.

This contradicted my early hunch that a mistake of that sort would cause a NullPointerException. I think at one point I actually wrote a unit test that expected a NullPointerException to happen, not an ArrayIndexOutOfBoundsException.

Maybe I still would have eventually discovered that problem without the help of a REPL. But with the REPL, it’s much easier to ask “What about this other case?”

I have to confess that I was and still am confused about how to actually install the Scala REPL on your system, even though it’s obviously something I have done on my system.

I had IntelliJ download the Scala plug-in, but, as far as I can tell, that does not include the Scala REPL. Next I downloaded LLVM/Clang, but still, no Scala REPL.

If I remember correctly, what I finally did to get the Scala REPL was to go to the Scala downloads page, scroll down to “Other ways to install Scala” and click the “Download the Scala binaries for Windows” link.

I did take a look at Ammonite, which is said to be “a popular Scala REPL,” but I have not installed it, much less used it.

Okay, now we can get to the nuts and bolts of actually using the Scala REPL as a Java REPL.

Once you have the Scala REPL on your system and adjust your operating system’s environment path variable, you can run the Scala REPL from the command line with the command scala.

If you don’t feel like adding it to your system’s path, you’ll have to navigate to the scala\bin directory before you can start the REPL.

The most straightforward way to load your Java project into the Scala REPL is with the JAR file at the command line. Let’s say the Scala REPL is in your path variable and you have navigated to the folder with the JAR.

On NetBeans, the JAR folder path might be something like NetBeans Projects\MyProgram\dist\MyProgram.jar.

On IntelliJ, it might be more like IDEA Projects\MyProgram\out\artifacts\myprogram_jar\MyProgram.jar. I don’t know about Eclipse.

Then you type in something like scala -cp MyProgram.jar. Give the JVM a second or two to start up. You should see something like this:

First I’d try something very simple, just to make sure everything’s in working order.

Next, to remind myself that this is Scala, not Java:

That res0 and res1 stuff is so that you can access previous results. You can do something like res0 + 1, for example.

Maybe there’s a better way, but as far as I can tell, to access the classes you loaded with the JAR file, you need to qualify the class names with the relevant package names, e.g., mainpackage.MainClass to access MainClass in mainpackage.

In my case, I loaded a very recent version of my ImaginaryQuadraticInteger project (available from my GitHub repository).

That one consists of two packages: imaginaryquadraticinteger (which contains almost all the code) and filefilters. Maybe the project needs to be broken up into smaller packages, but that’s a discussion for another day.

So, to create a new ring object, just new ImaginaryQuadraticRing won’t do.

Uh oh. The square root character was changed to a question mark. It seems that all the console fonts on my system are strictly limited to ASCII.

Well, both ImaginaryQuadraticRing and ImaginaryQuadraticInteger have toASCIIString() functions. Hmm… maybe I could create Scala classes that extend those two classes for the sole purpose of rerouting toString() to toASCIIString().

But if I’m going to do that, I might as well overload the basic arithmetic operators. Like, for example, the plus operator for ImaginaryQuadraticInteger, which I put in the Scala class I’ve named ImagQuadInt:

In most Scala operator overload examples, you’ll see that or other to refer to the second operand. Neither of those is a reserved Scala keyword, so I prefer to use a more meaningful word, “summand” in this case.

If you want to see the subtraction, multiplication and division overloads, they’re all in the GitHub repository I linked earlier.

So now in the Scala REPL I can do stuff like this:

Obviously numberC can’t be prime. I wrote a function to make that determination in the NumberTheoreticFunctionsCalculator class of the imaginaryquadraticinteger package. At this point I’m really wishing I had given that one a shorter name, like maybe NTFC.

Some of you might be thinking “big deal, so what, Wolfram Alpha can do that.” Yeah, as long as you don’t ask that question about a prime number like 1 + √−2.

Mathematica wouldn’t be able to make that determination either, not unless you programmed it for that, or if they add that capability in a future version.

Lastly, I’d like to leave you with an example of something that feels almost ridiculous in a REPL: throwing and catching exceptions.

I hope this gives you a taste of what can be done in the Scala REPL.

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