Blog

Why you should use Scala in your early stage startup

Valentin Lehuger
Valentin Lehuger
Oct 14, 2020 · 3 min read
Scala logo

Why use Scala? We listed the advantages of Scala we see in our startup. See whether the benefits of Scala could help you too.

Advantages of Scala [TL;DR]

1. Focus on what matters: Expressiveness + High order functions

2. Get less bugs: Statically typed + Clean error management by design

3. Benefit from JVM ecosystem: Performant libraries + Good tooling environment

4. Attract talents

What is Scala

Scala is a JVM based language. It’s flexible, you can write code in both imperative or functional styles. Scala is a pragmatic language that mixes the best of functional and object-oriented programming. It basically means that you can create classes to encapsulate state and methods but you can’t mutate them.

1. Focus on what matters

The main power of Scala is to let the developers focus on what’s most important.

Expressiveness

Running on the JVM, Scala is as powerful as Java but it is way clearer and more concise. It makes the code easier (and faster) to write and read!

For example, look at how we create a list of string in Java vs Scala:

Java:


      List stringNumbers = new ArrayList();
      list.add("3");
			list.add("5");
			list.add("7");
			list.add("11");
      


Scala:


      val stringNumbers = List("3", "5", "7", "11")
      


High order function

High order functions are functions that abstract some control structure like a loop to update every element of an array.

They’re the functions we use most in Scala. They work by taking a function as a parameter. Used with anonymous functions, they’re perfect to focus on implementing the business logic instead of juggling with indexes to increment and stop conditions.

Look at how we can convert this list of string into a list of integers:


stringNumbers.map(x => x.toInt)
// Here x => x.toInt is my anonymous function

// We could even simplify it like
stringNumbers.map(_.toInt)
			

We can also compute the sum of it by using the high-order function fold:


      stringNumbers
	.map(s => s.toInt)
	.fold(0)((accumulator, num) => accumulator + num)

// Even more idiomatic
stringNumbers
	.map(_.toInt)
	.fold(0)(_ + _)
  

2. Get less bugs

Statically typed

By checking the type during the compilation, Scala type system reduces considerably the amount of bugs caused by type errors.

Type inference allows typing without being too verbose:

def square(x: Int) = x * x 

Here the type of square (Int) is inferred from the * operator which multiplies an Int by an Int giving an Int in output.

And thanks to pattern matching, we can still write flexible code:


      abstract class Vehicle

case class Bike(color: String)
case class Car(brand: String, model: String, energy: String)

def isGoodForEnvironment(vehicle: Vehicle): Boolean =
	vehicle match {
		case Bike 				 => true
		case Car(_, _, "electricity")  => true
		case Car(_, _, _)  	       => false
	}

Here we can even decompose an object to pattern match on its attributes. We can even add pattern guards (if condition in a case), pattern match a regex or the elements of a List.

Clean error management by design

Option and Either

There are some useful standard types in Scala to manage errors. The most commonly used are Option and Either. An Option can either be a class Some containing a value or a None object. So we can associate a valid result to Some and an error to None. Let's write a function to safely update a String to Int.


def convertStringToInt(input: String): Option[Int] =
Try(input.toInt).toOption

// convertStringToInt("5") => Some(5)
// convertStringToInt("Err") => None

And if we need an error message we can use the Either class that will return a Right containing the value or a Left with an error type.


      def convertStringToInt(input: String): Either[Throwable, Int] =
	Try(input.toInt).toEither

// convertStringToInt("5") => Right(5)
// convertStringToInt("Err") => Left(java.lang.NumberFormatException: For input string: "Err")

Try is also a great type to manage error, especially to encapsulate every call to Java functions that can throw errors.

Combine them with for-comprehension

Option, Either or Try allow us to return a result or an error and not throw it to whatever will catch it. And thanks to a special Scala control structure, the “for-comprehension”, we can easily combine them to return the first error encountered.


def convertStringToInt(input: String): Either[Throwable, Int] =
	Try(input.toInt).toEither

def safeDivision(dividend: Int, divisor: Int): Either[Throwable, Int] = Try(dividend / divisor).toEither

def safeStringDivision(dividendStr: String, divisorStr: String): Either[Throwable, Int] =
for {
	dividend <- convertStringToInt(dividendStr)
	divisor  <- convertStringToInt(divisorStr)
	result   <- safeDivision(dividend, divisor)
} yield result


// safeStringDivision("10", "2") => Right(5)
// safeStringDivision("WRONG", "3") => Left(java.lang.NumberFormatException: For input string: "WRONG")
// safeStringDivision("10", "ERR") => Left(java.lang.NumberFormatException: For input string: "ERR")
// safeStringDivision("10", "0") => Left(java.lang.ArithmeticException: / by zero)

dividend on the left part of dividend

Perfect to handle asynchronous code

“for-comprehension” are also amazing to work with asynchronous code like HTTP calls encapsulated in a Future. We can combine them and return an error for the first error we encounter.


      def priceOfCryptoInDollar(crypto: String): Future[Int] = {
	// Call to coinbase
}

def compareCryptoPrices(firstCrypto: String, secondCrypto: String): Future[Int] = {
	for {
		firstPrice  <- priceOfCryptoInDollar(firstCrypto)
		secondPrice <- priceOfCryptoInDollar(secondCrypto)
	} yield firstPrice - secondPrice
}

// compareCryptoPrices('ETH', 'DTH') => Success(352.10)
// compareCryptoPrices('WRONG', 'DTH') => Failure('WRONG is not a correct crypto')
// compareCryptoPrices('ETH', 'ERROR') => Failure('ERROR is not a correct crypto')

We can even combine Future with other error types like Either by using functional libraries like cats.

3. Benefit from the JVM ecosystem

JVM allows to use powerful java libraries

For example we use db connectors, libraries to manage timestamps, logging & monitoring clients and more!

Good tooling environment

There is a great IDE with Intellij Idea. The community also built a very efficient alternative Metals, a plugin that can transform your VS Code in Scala IDE.

Another useful tool we use is sbt-docker. It allows you to simply build a docker container embedding your application.

4. Scala attracts talents

Such powerful language attracts skilled engineers who are curious and keen to test new tools, who have the willingness to discover new paradigms, new perspectives to see the world of programming... And this is the perfect mindset to join a startup as Engineer 1 to 10!

 

By the way, we’re hiring if you want to join us at Actiondesk.

Keep reading

X
Please wait...
Oops! Something went wrong while submitting the form.