1

New Research Report - Exploring the 2024 State of Software Quality

Group 370
2

Codacy Product Showcase: January 2025 - Learn About Platform Updates

Group 370
3

Group 370

Learn Scala: An Intro For Developers (Part 1)

In this article:
Subscribe to our blog:

Learn Scala (Part 1) – Introduction

Scala is my favorite language to program nowadays. Before I learned Scala, I used to code in C#.  C# was actually the language that first introduced me to the amazing world of functional programming living together with the Object Oriented paradigm (C# Linq was an eye opener for me at the time).

Using functional techniques on a paradigm that I was used to seemed really cool, so I searched for some modern languages that treated functions as first class citizens and stumbled into Scala. Oh, what an amazing rabbit hole to enter…

In this Part 1 of a series (check out Part II) we’ll introduce features and techniques that make learning Scala so worthwhile. My intention is to target developers with Java/C# background. A lot of people at least know the basics of Java, and most people I know that use Scala (myself included) come from either a Java or a C# background.

Keep in mind that Scala is a really powerful language. On a future blog post when we talk about implicits, you will hear Uncle Ben in the back of your head. But for now let us try to see some of the Scala awesomeness without going too deep.

How to draw an owl

Have you learned how to draw an owl? Well, Scala and functional programming can feel like that, more often than not. It is assumed that you know what higher-kinded types are as well as other features or techniques, like Type Classes or Monad Transformers. I hope that with this series, I will help you understand the missing steps so that you too can draw that beautiful owl.

The better Java/C

A lot of people come to Scala from Java or C#, so starting to look at Scala like a better version of those languages is really appealing. By “better” I don’t mean that there is more tooling, or that Scala is more mature (because it is not). I will be focusing on the syntax and the way that we can apply functional principles to do really cool and clean pieces of code in Scala.

The functional way

Once you go functional, you never go back. But why is the functional way “better”? What are the big advantages that it brings?

Let’s say that we have a list of integers, and that we want a new one with all those numbers squared. What do we need to “say” to the computer to do in order to achieve that?

Classic approach using Java, we need:

  • A new empty list to store the squared values
  • To iterate though the original list
  • To square each number and store it on the new list

This is fine, everybody has done it in the past, and it does work very well! But let’s try to take a step back and note that, for even a small example, we need to “say” how the computer should behave. If we start with an empty list, or on how to iterate should be decided by the computer, it would be nice if we could only focus on the logic itself. In this case, how to square a number.

There are some very important and cool methods that we rely upon to write functional code. Today we use the one that can help us with the problem at hand. Let’s take a look at .map, and tackle the square numbers problem in a nice and clean functional way.

.map

Iterating through collections is something really common, there are many use cases where you want to apply a transformation to each item in a collection and, for that, .map is here.

Given a collection and a function that knows how to handle the items of that collection, you can use .map to make that transformation. With our previous example, we have a collection of numbers, and a square function that knows how to square a number. We have everything we need to use it.

Classic Java

int[] numbers = {1, 2, 3};
ArrayList<Integer> numbersSquared = new ArrayList<>


//Traditional 'for' using indexes
for (int i = 0; i < numbers.length; i++) {
    numbersSquared.add(numbers[i] * numbers[i]);
}

//Better alternative using 'foreach'
for (Integer n : numbers) {
    numbersSquared.add(n * n);
}

Scala

//Scala functional way
val numbers = List(1, 2, 3)

val numbersSquared = numbers.map(n => n * n)

This is more like it! In Scala we just need to care about the transformation, call .map on the collection with it, and we are done. The numbers collection remains safe, .map does not change the numbers collection, it returns a new sequence of numbers with the applied function passed to map.

On a related note, Java 8+ does have .map, which is great in theory, but let’s take a look in practice.

Java8+ functional

//Java 8+ version functional way
int[] numbers = {1, 2, 3};

int[] squaredNumber = Arrays.stream(numbers).map(n -> n * n).toArray();

I think it is great that Java is trying to add functional ways of programming, however the need to convert to streams and Collectors.toList (on another cases with List) adds too much boilerplate for my taste. Do feel free to try it in Java, it may be a nice bridge for you to come to Scalaland!

This is the tip of iceberg, as .map allows us to taste the functional goodness. On the next blog post we will see how .map, together with .filter and .reduce/.fold, is essential for functional world toolkit and how they enable us to work well with immutable data.

Immutability

Speaking about immutable data, immutability is great and life is just happier when you program using it. It’s that good. But let’s be honest, it is harder to think about solutions using immutable data. We are really comfortable on Objects with state and logic that changes it during the program execution. It has been so natural for the past few years that it makes sense: how can we change our objects if we cannot change them??

Before digging into how can you get stuff done with immutable data, let’s start by taking a look of some of the advantages. It is thread safe (read-only, so read it as you please). No one can change it: it doesn’t matter how many other methods have references to your objects, you can safely return a list of animals knowing that no one will insert or remove a Giraffe from it. You can also rely on the value of the variables throughout the execution, as it does not matter which flow of if-else was followed, you know that they will not change.  Finally, it’s less error-prone and easier to debug, as the value of an immutable variable is initialized together with the declaration of the variable.

Java and mutability

List<String> greetings = new ArrayList<>();
greetings.add("Hi");
greetings.add("Hello");

foo(greetings);
bar(greetings);

//How can we be sure of the content of greetings at this point??

Even if you add final to the List, it will not accomplish much as anyone can still add elements to the list. Wouldn’t it be great if you know for sure that greetings cannot ever be modified? Not being able to add more items, or to change the ones that are already there?

Scala will do that by default! You just need to allow for Scala to help you because, if you don’t, you can force mutable List, or use var instead of val.

Var instead of Val? Immutable by default? Scala syntax? What’s next?

As you probably noticed, I didn’t cover any Scala syntax, or what the val is that I used on the square numbers example.

The main goal of Part 1 is to give you a taste of the strength of Scala. This lets you try the functional and immutable world in all its glory while allowing you to maintain some familiarity with the Object Oriented world. If you are already sold, I suggest you to take a look at Programming in Scala, Third Edition.

The syntax has some core differences from Java, but that is the easy part when talking about a mind shift around functional programming and immutable data (Pro tip: IntelliJ even has code conversion when you paste Java code on a Scala file).

If you start to toy around with Scala, also check static analysis tools like Scalastyle, which can really suggest good practices. It will, for instance, warn you that you should use val instead of var and explain why. (Pro tip #2: Codacy will do static analysis out-of-the-box for Scala)

I hope I kept you interested, and I invite you to stay around. For the next posts, we will be focusing on how to write code that is immutable using mostly .map,.filter, and .reduce/.fold. We’ll be also taking a look at case classes and some pattern matching. If you have any suggestion or anything that you like to see next, feel free to ping me on Twitter @machadoit.

Until the next time, see you in Part 2!

Want to learn more now? Check out more Scala resources on our blog.

About Codacy

Codacy is used by thousands of developers and teams to analyze billions of lines of code every day!

Getting started is easy – and free! Just use your GitHub, Bitbucket or Google account to sign up.

GET STARTED

RELATED
BLOG POSTS

Scala: Learn to walk before you fly (Part 2)
Part 2 – Building immutability Welcome back to Part 2! In Part 1 we saw Scala as a language that facilitates and drives you towards the...
Why use Try instead of Scala Try Catch
Scala try catch is always an option when writing Scala code for Java like exception control flows. However, you also have the option of start using the...
How to make the Scala compiler review your code
This is a blog post by our own Pedro Rijo on how to make the Scala compiler help you in reviewing your code. The original post can be found here.

Automate code
reviews on your commits and pull request

Group 13