Programming with Functions #1: Introduction

Maciek Gorywoda
Nerd For Tech
Published in
9 min readDec 8, 2020

--

Functional Programming. The only possible way to write code according to some, a muddle of special characters and magic spells used by hipsters to show off according to others. In this series, I’ll try to convince you that it’s neither. Or maybe it’s both. I haven’t decided yet.

This is the first of a series about FP basics in Scala. It’s also my “manifesto” of a sort about simplicity in programming. I feel that in our quest to learn Functional Programming we sometimes skip over foundations and dive straight into advanced stuff. In consequence, naturally, the foundations of our code are often shaky. If you start learning FP right now, I’d ask you not to do that. Instead, forcus for a while on what this series talks about. The next video will be released in a week or so, and the next ones will appear once a month or a bit more often than that.

The problem lies in that human minds like to think in extremes. Black and white, with no grey in-between. Day and night. Pizza and pineapple. We like clear borders between concepts, so we can put ourselves in this or that camp and take part in Twitter’s holy wars. The idea that we could merge two positions, picking up the good stuff from both, often seems to us either as an impossible hippie fantasy where we should all just love each other and everything will be awesome, as the golden mean fallacy, or as a rotten compromise where the result is something everyone is equally unhappy with. So if on one hand, we have Functional Programming, often associated with safe and sound, but very difficult to write and understand code, and on the other we have imperative code that can look simple and be easier to write but is also prone to errors and a real pain when it comes to refactoring. So, having these two as extremes, the middle between them often looks like a place where the code is neither simple nor safe. And we don’t want to be there, so we choose one of the sides and go to Twitter to fight.

Already in the 18th century, Immanuel Kant wrote about how progress in the world of ideas takes the form of a triad: a thesis, an antithesis, and a synthesis: „a progression of three ideas or propositions in which the first idea is followed by a second idea that negates the first, and the conflict between the first and second ideas is resolved by a third idea” [wiki]. The third idea, the synthesis, becomes then a new thesis and the cycle repeats itself. In our case, we can say that imperative and functional programming are the thesis and the antithesis of each other, no matter which one is which one. Functional programming is the more academic idea addressing imperative programming problems with safety, concurrency, and tons of errors in every bigger project, and Imperative Programming is a more business idea addressing the functional programming problems with being utterly cryptic, too abstract, and unfit to solve real-life problems.

Immanuel Kant never heard about programming. I mentioned him only to show off. Sorry.

And yet I believe that it is possible to follow a middle way that is both simple and safe. We can write in a functional style and our code can still be pretty minimalistic and readable, and we never ever have to use the word „monad” to explain it. But in order to do that, we have to talk for a moment about what Functional Programming really means. Yes, it is a programming paradigm closely connected to lambda calculus, and as such it’s littered with mathematical jargon and abstractions which let us handle certain characteristics of our data in isolation, declare rules about them, and use those rules to gain an advantage over the situation when we wouldn’t do it. But it doesn’t mean that you have to have a Master’s in Computer Science in order to be a functional programmer (trust me, I have a Master’s in Computer Science).

1.1. But first a few words from the author

What is this about?

This is going to be a series of YouTube videos about how Functional Programming can help you write code that is concise, and yet readable, and yet again scalable, meaning that if your project grows significantly, you will still be able to use the same code after some refactoring. The videos will be backed up by blog posts on my WordPress, and copied to Medium. (I hope this way I will find some more readers). I admit it’s going to be a bit tricky to keep this format from falling apart: not every piece of information can be presented as well in a blog post and a video. I will probably make small changes to the blog posts long after they’re published to make them match the videos (which are harder to edit, so I won’t make as many changes on that side). For videos, I use the app called VideoScribe which creates whiteboard animations, and that makes it possible to use images from it to illustrate the blog posts. For sure there will be a lot of links taking you from the blog to the video and back. Still, I expect there will be some differences, so please don’t treat the blog as transcription of what’s being said in the videos.

I would describe this series’ level of difficulty as lower-intermediate. You should already know basics, have gone through some tutorials, and have written at least one smaller project. If you’ve done that and now you wonder what’s next, this might be a good moment for you to read or listen to this. Personally, I find that this is the moment in learning when many people lose direction and start to wander around, learning a bit of this and that, until they find a niche, a language, or a technology, they get interested in. I want to help you a bit.

KISS over DRY

The reason for this series is to convince you that simplicity, not complexity, is the trademark of good programming and that Functional Programming is a great tool to achieve it, despite the impression you might have gotten from some FP conference talks. Simplicity is a nebulous term. It stands in opposition to complexity, but it’s not crudeness — which in programming means writing things such that they “just work” but don’t scale or will fall apart under the slightest modification. Simplicity goes along with the DRY principle (“Don’t Repeat Yourself”) but only to the point where the developer starts to make code generic and abstract in places where it’s going to be used only in one specific way. It helps with performance by avoiding unnecessary complexity and making bottlenecks more evident but keeps you from spending nights optimizing rare corner cases and rewriting code in a more low-level technology. But what’s most important, it makes code readable. Even if it didn’t have other advantages, this one should be enough. [link]

Dans ses écrits, un sage Italien
Dit que le mieux est l’ennemi du bien.
Voltaire

Programming is a team effort. The days when programs were written by individuals, closed off from the world in their basements and garages, are long past and (hopefully) forgotten. You need to write code in a way that your teammates — as well as you in a few months — will understand.

And yet we usually associate simplicity with the beginner’s level and tend to think that as we progress as programmers we should write more complex code. And the other way around: when we see two programmers, one doing some simple stuff and the other writing complex code, we often jump to the conclusion that the second one is the more senior of them. It’s called a complexity bias and it’s present in all aspects of life, from art to machinery. For years I trained aikido, a Japanese martial art full of fluid movement, throws, and joint locks. Aikido techniques are complex and beautiful. Most of them are also not very good at self-defense. You know what works instead? Kickboxing.

That’s not to say that complex programming techniques are useless and you should always stick to the basics. You can — and you should — learn more complex stuff when you feel confident enough. The trick is to know the basics so well that you’re able to recognize when the complex techniques work to your advantage, and when the same can be achieved in a simpler way or the advantage over the alternative is not worth introducing the additional complexity [The law of diminishing returns]. So this series of posts is about that: basics of functional programming. It’s about how different concepts that are more or less associated with FP work together and can give you solid foundations for future studies. Learn this, and then go, conquer the FP world with its monads and whatnot.

Languages

My work is mostly in Scala and this is the language I will use for code examples. But this series is not about learning Scala. You can use certain elements of Functional Programming in many other languages. Haskell, of course, but I don’t have much experience with Haskell. Other languages I use and like are Rust and Kotlin (Kotlin fares remarkably well in this area when mixed with the Arrow library). Also, I heard some good stuff about Swift, and the new versions of Java tend to incorporate more and more elements of FP, clearly inspired by Scala and Kotlin. To be honest, programming communities around many old programming languages are looking in this direction: check out, for example, this blog entry about writing FP in C# by Igal Tabachnik.

Across the series I will try to explain what I’m talking about in the way that doesn’t require you to know Scala. In fact, if you know Scala, you might find some parts of this series boring. Feel free to skip forward. Just make a mental note that this is what I find useful — everything I talk about here comes from my experience as a Scala developer, and I try to be as concise as possible (except for jokes). But if you never wrote anything in Scala you may find some of the terms confusing. If so, please let me know, and I will try to improve the script.

There’s only one thing I am adamant about when it comes to choosing a programming language — it must be statically typed. Even if such languages are a bit more difficult to learn at first, type safety provided by a good static type system cannot be overestimated when we start working with bigger projects. They help us understand the code, help us refactor it, provide us with minimalistic documentation, and save us from countless bugs. In my opinion, and this is the hill I will die on, dynamically typed programming languages are good only for writing small to medium-sized scripts and should not be used in big projects. (We will talk about type safety in one of the next chapters).

You may also be interested in this: https://www.fpcomplete.com/blog/2018/10/is-rust-functional/

And that’s it for now. Since this video is only an intro to the series, I will try to release the next video pretty soon, and there we will start to go deeper into technical details. Namely, we will talk about functions as data, and about total and partial functions.

By the way, English is not my native language, and so I’d like to take this moment to thank Jon Pretty for checking my script, and also Jon Pretty and Daniel Westheide for lots of insightful comments. And I’d like to thank my team at Wire where I work. This series started as a talk I gave for my team about how certain concepts in Scala can be translated to Kotlin. The more I thought about it, the more it grew. And now, after more than half a year, it’s this: a series of ten videos, each around ten minutes long, give or take. I hope you’ll enjoy it.

Next: Programming with Functions #2 — Functions as Data

The “mindmap” of this episode (PNG, 2MB)

If you want to help me translating the video’s subtitles, here you can download their English version, and then please find me on Twitter: @makingthematrix.

--

--

Maciek Gorywoda
Nerd For Tech

Scala. Rust. Bicycles. Trying to mix kickboxing with aikido. Trying to be a better person too. Similar results in both cases. 🇪🇺 🇵🇱