Over a million developers have joined DZone.
{{announcement.body}}
{{announcement.title}}

FP in Scala for OOP Programmers (Part 1)

DZone's Guide to

FP in Scala for OOP Programmers (Part 1)

If you come from a Java/OOP background and wanted to know more about functional, declarative programming, Scala is a great to get your feet wet.

· Java Zone
Free Resource

Get the Edge with a Professional Java IDE. 30-day free trial.

Have you ever been to a Scala conference and told yourself, "I have no idea what this guy is talking about?" Did you nervously look around and see everyone smiling, saying, "Yeah, that's obvious?" If so this post is for you. Otherwise, just skip it. You already know FP in Scala.

This post is optimistic, and although I'm not going to say functional programming in Scala is easy, our target is to understand it, so bear with me. Let's face the truth: functional programming in Scala is difficult if you are just another working class programmer coming mainly from a Java background. If you came from a Haskell background, then, hell, it's easy. If you come from a heavy math background, then hell yes it's easy! But if you are a standard working-class Java backend engineer with an OOP design background, then hell yeah it's difficult.

Scala and Design Patterns

An interesting point of view on Scala is looking at its set of features as design patterns. This is exactly what Ivan Nikolov says in Scala Design Patterns. He actually shows how the hybrid nature of Scala makes some traditional object-oriented design patterns obsolete, or possible using other, cleaner techniques in his great book. While I fully agree with him, I recognize that it's going to take a lot of time going over all the standard design patterns — not only the standard ones, but also many of the unwritten patterns and best practices to see how they work in the Scala programming language.

Terminology

Let's start with the terminology: monad, semigroup, functor, typeclass, higher order functions, higher order types, partially applied functions, partial functions... are you still with us? If you already know the above concepts, then this post is not for you. But if you aren't very familiar with them, then read on! But I have no chance of going through them all in a single post, so follow along with this series!

A Simple Example

Question, is the below code easy?

object Request {
    def pure[A](a: A): Free[Requestable, A] =
        Free.liftFC(Pure(a) : Request[A])

    def fetch[A](service: Service[A]): Free[Requestable, A] =
        Free.liftFC(Fetch(service) : Request[A])
}


Not for me. What are all those terms? "Free", "lift", "pure", and what are the generics doing there? I can find thousands of examples like this — just search Google for the cool FP terminology. This is our target: to decompose this structure, to clear out the fog.

Haskell

I think if you want to learn Scala, you first need to learn Haskell or something else before moving onto it. Otherwise, it might be pretty difficult to wrap your head around these concepts. And yes, when I need to learn a concept in Scala, I first learn it in Haskell and only then move to Scala. If Haskell only had the Java libraries and would run on the JVM...

FP Is Very Important

But FP is very important: concurrency, better code, Big Data, parallel computing, better testing. I mean, FP is the thing for a programmer who wants to write clean code with a clean, pure core and all the IO surrounding it. It's the dream of clean code, so we are going to make that effort.

The Good Thing About FP

The good thing about FP is actually what creates all the problems and noise for those with OOP backgrounds. With FP, you use pure functions. I assume we all know what that means. The problem is that real world applications are not pure — they have side effects. And this is where much of the complexity comes into play. This is the challenge. In addition to that, you don't mutate things, so you start using recursion.

The Benefits of Imperative Programmers

Before I get assassinated by functional programmers, I want to tell you this: There are good things about imperative programming. If you have some basic sanity about clean code practices and you write well-organized and clean code with imperative programming, (small functions, mutation where needed but not always), you use for loops instead of the map/flatMap twins, then you know what? Use the Java util concurrency building blocks and non-blocking I/O with multithreading and write excellent applications with high performance utilization. I know this first hand: I wrote many such apps some with very high scale demand, and I have to say that for other programmers without major knowledge of FP, those imperative programs were much easier to understand than their FP siblings. So imperative is also good. But we are here to get to FP, not to imperative. And this is the route we are going to take.

Declarative vs. Imperative

So the first step is to understand what declarative code means.

I like Jenkov article "The illusion of declarative code." It presents the following imperative code:

function capitalWithInterest(capital, interest, periods) {
    var result = capital;
    for(var i = 0; i < periods; i++) {
        result = result * (1 + interest);
    }
    return result;
}


Then the article asks for the declarative version of that code. The answer?

var result = capitalWithInterest(100, 0.1, 5);


It's declarative. We didn't imperatively say how we want to calculate capital with interest. We just told the computer that we want it to calculate the capital with interest for us.

Declarative Code With Scala

So in Scala, the most common example of declarative code is by using "map" and friends instead of for loops. For loops are the explicit, imperative way of telling the computer how to do the loop. Map and friends are declarative, you just tell the computer to go over the items on this list and subtract 2 from each.

val listOfNumbers = List(1,2,3)
listOfNumbers.map(_ - 2).foreach(println) 


So in this case, instead of imperatively going through the list and printing each one, we tell say, "Hey, please subtract two from each item in the list (map) and print the result."

Functional Programming and Immutability

Because, in functional programming, we would rather have pure functions, then, there is a consequence to that. The consequence is that we use immutability more and more — as much as we can instead of mutable data structures. In the great book Scala Design Patterns by John Hunt, the author says, "Immutability is an important principle in Scala and it should be preferred. The builder design pattern with case classes uses immutable fields and this is considered a good practice." And yes, case classes which inherit from sealed traits are not only a great way to model your data, they help extensively with using immutable data structures instead of mutable ones.

Summary

We have just touched the tip of the iceberg here, but don't worry — before global warming takes its place and melts the iceberg, we are going to hit upon all the concepts you wanted to know about Scala but had nightmares about: free monads, managing state, functors, and their friends.

Get the Java IDE that understands code & makes developing enjoyable. Level up your code with IntelliJ IDEA. Download the free trial.

Topics:
scala ,java ,functional programing ,declarative programming ,tutorial

Published at DZone with permission of Tomer Ben David, DZone MVB. See the original article here.

Opinions expressed by DZone contributors are their own.

{{ parent.title || parent.header.title}}

{{ parent.tldr }}

{{ parent.urlSource.name }}