This book is separated in 15 chapters with specific subsections:
- Introduction: gives you a brief introduction about pragmatic software development, functional programming history and reason and how it is applicable to modern software development.
- Roots of the evil: presents language features that are more harmful than beneficial and later focuses on alternatives to solve the problems introduced by them.
- Meet ESLint: shows how to encourage writing functional code and restricting harmful language features by using a specific tool for that job.
- Modules: focuses on how to organize modular code and functions according to their domain and structuring the file system of your program. There is a special focus on modular code, code that is not specific for the program, but that can be easily reused and help you writing less.
- The power of composition: touches on what really functional programming is about and shows you how to create more complexes things by composing very simple ones. It is definitely like playing LEGO!
- Transforming values: talks about common data structures transformations and functions that help us modeling transformations and working with immutable data structures. We'll be using a library called Ramda to present it in practice.
- Monads, monoids and functors: may look a bit theoretical, but will present, together with the concepts of the terms, the practical usage of them and how important they are on the design of a functional program and how they help us to handle errors and deal with the dangerous world that exist outside.
- Async programming: is an overview about how to deal with time-dependent actions and asynchronous computations. We'll talk about promises, futures, generators and the task monad.
- Welcome to Fantasy Land: shows what is Fantasy Land and how it helps different functional libraries to easily interact and work together and shows some libraries that are compliant to this specification.
- A bit of theory: is definitely the most theoretical part of the book. We present the roots of functional programming and possibly advanced concepts.
- Solving real world problems: presents common daily problems and functional approaches, step by step, to solve them. It is not only about solving problems, but solving problems in such way that they will generate less problems later.
- Final considerations: is our "goodbye". It is not the conclusion, because software development approaches are evolving really fast, and assuming that a specific way to get the job done is the best for all the times is definitely foolish.
Most parts of this book are independent, so you can read chapters in the order you prefer, and the order we set here is only a suggestion (except for the final considerations, of course).
What does "pragmatism" mean?
When possible, we'll provide the problem that we are trying to solve with alternative implementations and techniques in other paradigms. Programming is made to solve problems, but sometimes solving a problem may generate several other small problems, and this is where we will touch; this is what we will try to avoid. Before continuing, we need to set some premises:
Programming languages are not perfect: seriously. They are built and designed by humans, and humans are not perfect (far from that!). They may contain failures and arbitrarily defined features, however, most times there is a reasonable explanation about the "workaround".
Problem solving may generate other problems: if you are worried only about "getting shit done", this might be a bit controversial for you. When you solve a problem, have in mind that your solution is not free from introducing problems that other people will have to solve later. Being open to criticism is a good thing here; this is how technology evolves.
The right tool for the right job: this is pragmatism. We pick the tool that solves the problem and introduces the lowest number of side-effects. Good programmers analyse trade-offs. There are a lot of programming languages published and dozens of paradigms, and they are not made/discovered only because "somebody likes writing that way" or "somebody wants to have their name in a programming language" (at least most times), but because new problems arise. It is sensible, for example, to use Erlang on telephone systems, Agda on mathematical proofs and Go on concurrent systems, but it is definitely insane to use Brainfuck on web development and PHP on compiler development!
Marcelo Camargo is a cute brazilian programmer and one of the main evangelists of the paradigm in Brazil. He is the designer of the Quack programming language and colaborator or maintainer of dozens of open-source projects, such as the first unnoficial version of Skype for Linux and improvements on the PHP language. He loves type theory, capybaras and has a cute black cat that is almost always with him while writing. You can find him on GitHub under
/haskellcamargo or write him a letter on firstname.lastname@example.org.
The second chance
And God said, "let there be functions", and there were functions.
In the beginning, computers were very slow, way slower than running Android Studio on your 2GB RAM machine! When the first physical computers appeared and programming languages started to be designed and implemented, there were mainly 2 mindsets:
- Start from the Von Neumann architecture and add abstraction;
- Start from mathematics and remove abstraction.
When it all started, dealing with high levels of abstraction was very hard and costly, memory and storage were really small in power, so imperative programming languages got a lot more visibility than functional ones because imperative languages had a lower level of abstraction that was way easier to implement and map directly to the hardware. It could not be the best way to design programs and express ideas, but at least it was the faster one to run.
But computers improved a lot, and functional programming finally got its deserved chance! Functional programming is not a new concept. I'm serious, it is really old and came directly from mathematics! The core concepts and the functional computational model came even before physical computers existed. It had its origins on lambda calculus, and it was initally only a formal system developed in the 1930s to investigate computability.
A lot of modern programming languages support well functional programming. Even Java surrended to this and implemented lambda expressions and streams. Most of you program in languages that were created; I want to show you the one which was discovered.
Why functional programming?
If imperative programming and other paradigms, like object orientation, were good enough, why do we need to learn a new way to code? The answer is: survival. Object orientation cannot save us from the cloud monster anymore. More complex problems have arisen and functional programming fits them very well. Functional programming is not "another syntax", as some people think; it is another mindset and a declarative way to solve problems. While in imperative programming you specify steps and how things happen, in declarative (functional and logic) programming you specify what has to be done, and the computer should decide the best way to do that. We've evolved a lot to do the job that a computer can do hundreds of times better than us.
Testability and maintainability
Modular and functional code bases are way easier to test and get a high coverage on unit tests. Things are very well isolated and independent, and by following all the main principles you get composable programs that work well together and have less bugs.
This is really variant with the implementation, but in languages that can track all sort of effects, you get parallelism and the possibility of clustering your program for free.
Less is more
We'll focus more on program semantics and correctness than execution, but if you really want to learn, only reading this book will not be enough.