Connecting...

W1siziisimnvbxbpbgvkx3rozw1lx2fzc2v0cy9zawduawz5lxrly2hub2xvz3kvanbnl2jhbm5lci1kzwzhdwx0lmpwzyjdxq

Scastie provides an easy start for learning Scala by Alonso Del Arte

W1siziisijiwmtkvmdmvmtuvmtevmjgvmjavotiwl3blegvscy1wag90by0yndc4mtkgkdeplmpwzwcixsxbinailcj0ahvtyiisijkwmhg5mdbcdtawm2uixv0

Are you keen to learn Scala?

You can explore Scala using Scastie without committing to your computer's resources! How can you use it? Check out this article by Software Developer, Alonso Del Arte and begin your Scala journey. 

 

'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.

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
  • Adjust Build Settings
  • Edit and share Code Snippets
  • View the Console
  • Give Feedback

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.

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.

The example that I like to use is the Euclidean GCD algorithm. It’s an example I’ve used in the past and will likely use again in the future.

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 * -n

euclideanGCD(-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.'

 

This article was written by Alonso Del Arte and originally posted on Medium.