What I've noticed while coaching and teaching functional programming is that there are several common milestones that happen consistently. People will reach a certain level of skill, they'll get stuck, then they'll have a breakthrough moment where they reach a new level. I've started mapping out what I'm calling milestones. People usually start their functional journey with a particular language, so they have to learn the syntax first. That's where this map starts.
I bring this up in the Career Guide because I think awareness of our skills and potential can help guide us when we get lost. I hope it serves as a map as you develop in functional programming.
Syntax of the language
The syntax is the first stumbling block of the language. It can be a problem for some if they have only learned one syntax before. The primary skill is to write and read the language fluently.
After a time, the notion of scope becomes apparent. Many imperative languages do not have strict scoping rules, but they're the norm in functional languages. The primary skills to master at this stage are to identify what names are in scope and how to get values from outside of the current scope.
Expression-based evaluation model
Eventually, people realize that functional languages have a somewhat different semantic than imperative languages. Imperative languages are based on statements, while functional languages are expression-based. Expressions can be nested in ways that statements often cannot. This can be confusing, but over time people see the value. The primary skill is to identify the value of an expression instead of focusing on its behavior.
Reliance on return values
People learn that work can be done in functions, but that unlike in other systems, the best way to get the result of that work out is with the return value. This goes hand-in-hand with the expression-based semantics and ties into the later understanding of recursion and pure functions.
Effectively using recursion
Recursion becomes more natural to read and write at this stage. The primary skills they need to develop are identifying the base case and advancing the recursion at each step. They begin to see the advantages over imperative loops.
Differentiation between pure and effecting functions
After a while, people begin to develop an intuition about the benefits of pure functions. Pure functions can be called many times and don't depend on external state. The primary skill is to recognize effects and to separate existing code into pure and impure parts.
Recognizing when state is needed
After toying with totally pure programs, eventually a programmer will realize that state is sometimes necessary, but certainly not as necessary as they once thought. The primary skill at this point is to choose stateful constructs with the minimum properties they need to get the job done.
Mastery of immutable data structures
Immutable data structures are challenging to work with when they get complex and nested. Nonetheless, people achieve enough mastery to be more productive with them than they were without them. The primary skills are choosing the correct data structure for the problem and learning to use their apis effectively.
Using higher-order functions
Higher-order functions like map, filter, and reduce are often unfamiliar to people in imperative languages. Once they are learned, however, people will tend to use them over hand-rolled recursive solutions. The primary skill is to categorize the problem you are trying to solve into either a mapping problem, a filtering problem, or a more difficult problem and using reduce to solve it.
Writing higher-order functions
After people learn to use the existing higher-order functions, they can start to learn how to write their own. This is where people start writing functions that take functions as arguments and return new functions. They are comfortable with the notion of function as unit of computation, which was foreshadowed in their understanding of pure functions.
Building data transformation pipelines
When they have mastered immutable data structures and composing the three functional tools, and after separating out the effects from the pure code, they often begin seeing every problem as a data transformation problem. Data comes in (an effect), it is passed through a pure transformation, then it is sent along to another destination or store (another effect). The primary skill is composing up smaller transformations into the larger one that will solve the problem.
Algebraic modeling of a problem
I don't know if this is the final step, but it is important, if more rarely achieved. At this stage, one begins to build algebras--models of a domain with operations and guiding laws. The primary skill is modeling the essence of a problem with mathematical operations.
I hope that having this knowledge will give an advantage when setting out on a career in functional programming. Where are you on this journey? Have I left anything out? I'd love to hear about your journey. Where have you been, where are you, and where would you like to go?
Thanks again for being a part of this course. I'm here to help with anything you need. You can sign up for this course at the bottom of the page.
Action for the day:
The number one reason people don't get a job in functional programming is because they don't apply to enough jobs. If you've been following along, your ten jobs is already more work than 99% of aspiring functional programmers out there. But why stop at ten? I encourage you to go further and leave no decent job unapplied for. It's a lot of work but will get easier over time. And just imagine having a functional programming job!