Chapter 19: The functional journey ahead
This chapter introduction closes the book and previews advice on applying functional programming skills and continuing to learn.
After this chapter you will be able to
- Actions calculations and data skills. Describe how the first group of skills uses the distinction between actions, calculations, and data to identify problematic code, improve testability and reuse, and organize code.
- First-class abstraction skills. Describe the range of skills the section groups under first-class abstractions, from functional tools and data pipelines to reasoning about timelines and architectural coupling.
- Calculations within actions. Explain why identifying and extracting calculations from actions is worthwhile, and describe how actions, calculations, and data can be organized by rate of change.
- Higher-order function abstraction. Explain how higher-order functions reduce repeated low-level code and let programmers focus on domain code.
- Timeline execution control. Explain why ordering and repetition of actions matter across multiple timelines, and how timeline diagrams and primitives help address them.
- Skill acquisition curve. Describe how a new functional programming skill develops from enthusiastic use through failed experiments to a better sense of when to use it and when not to.
- Premature production application. Explain why applying a newly learned skill too eagerly in production code can be risky.
- Parallel tracks for mastery. Explain why developing skills need both a sandbox for experimentation and a production track for careful application.
- Small and playful project scope. Explain why a side project should start small and be whimsical: a small scope makes progress achievable, while playfulness leaves room to explore and change direction without worrying about failure.
- Focused practice on expandable foundations. Describe how to choose a project built with familiar skills, practice one new skill on top of them, and leave basic features that can be expanded later.
- Low-stakes exercise practice. Explain why isolated exercises are useful for practicing functional programming skills.
- Removing one global mutable variable. Explain why removing a global mutable variable can prevent bugs, and describe how to tackle one in an existing codebase.
- Fixing one problematic timeline. Describe how to use a timeline diagram to investigate a suspected race condition and eliminate an unwanted ordering.
- Incremental design improvements. Explain why improving production code one small step at a time is worthwhile, even when the benefits are not immediately visible.
- Logic extracted from actions. Describe how to improve an action with a lot of logic without trying to eliminate the action itself.
- Explicit action inputs and outputs. Explain how changing one implicit input or output to an explicit one improves an action.
- Functional replacements for loops. Describe how replacing individual for loops with functional tools contributes to an incremental shift in style.
- Practical functional language choices. Explain why the listed functional languages are presented as practical general-purpose choices.
- Job-oriented language choices. Explain which functional languages the section recommends for job seekers and how it distinguishes the two groups by available opportunities.
- Functional languages by platform. Describe how the section groups functional languages for browsers, web backends, mobile apps, and embedded devices, giving examples of the available languages or routes for each.
- Type systems as design guides. Explain why someone interested in static typing might choose a functional language to learn from, and name an example from the section.
- Lambda calculus and combinators. Explain that lambda calculus includes function definitions and calls, and that combinators are functions that modify and combine other functions.
- Category theory and effect systems. Describe category theory’s focus on structural similarities between types and explain, at the section’s high level, how effect systems use concepts borrowed from it to model actions with immutable data.
- Further reading by interest. Distinguish the four recommended books by the kind of functional-programming learning each offers.
What it builds on
- Part 1: Distinguishing actions, calculations, and data (chapter 1) · The distinction between actions, calculations, and data
- Part 2: Using first-class abstractions (chapter 1) · The book’s introduction of first-class abstractions as a part of functional thinking
- Extracting a calculation from an action (chapter 4) · Extracting a calculation from an action
- A functional architecture (chapter 18) · A functional architecture
- First-class functions can replace any syntax (chapter 10) · First-class functions replacing syntax
- The two fundamentals of timeline diagrams (chapter 15) · The fundamentals of timeline diagrams
- Summary: Manipulating timelines (chapter 17) · Manipulating timelines
- Principle: Minimize implicit inputs and outputs (chapter 5) · Recognizing implicit inputs and outputs when examining functions
Section by section
Introduction
This chapter introduction closes the book and previews advice on applying functional programming skills and continuing to learn.
19.1 A plan for the chapter
This section outlines the chapter’s plan for moving from learned functional programming concepts toward practical skill and further study.
19.2 We have learned the skills of professionals
The section recaps the professional functional-programming skills taught in the book, grouped into actions, calculations, and data and first-class abstractions.
- Actions calculations and data skills: Describe how the first group of skills uses the distinction between actions, calculations, and data to identify problematic code, improve testability and reuse, and organize code.
Why it matters: This grouping helps you recall how the book connects its design skills to practical improvements in code. - First-class abstraction skills: Describe the range of skills the section groups under first-class abstractions, from functional tools and data pipelines to reasoning about timelines and architectural coupling.
Why it matters: This grouping shows how the book’s abstraction skills apply to data processing, concurrency, state, and system design.
Key terms: actions, calculations, data, implicit inputs and outputs, immutability, stratified design, first-class abstractions, functional iteration, functional tools, data transformation pipelines
19.3 Big takeaways
This section distills the book into three takeaways: extract calculations from actions, use higher-order functions to remove repetitive code, and control when and how often actions run.
- Calculations within actions: Explain why identifying and extracting calculations from actions is worthwhile, and describe how actions, calculations, and data can be organized by rate of change.
Why it matters: Separating calculations from actions makes code easier to work with and helps guide its larger-scale organization. - Higher-order function abstraction: Explain how higher-order functions reduce repeated low-level code and let programmers focus on domain code.
Why it matters: Reusable abstractions leave more of your code focused on the problem it solves. - Timeline execution control: Explain why ordering and repetition of actions matter across multiple timelines, and how timeline diagrams and primitives help address them.
Why it matters: Making execution order and repetition visible helps you reason about bugs in software with multiple timelines.
Key terms: actions, calculations, data, rate of change, onion architecture, higher-order functions, abstraction, domain, temporal semantics, timelines
19.4 The ups and downs of skill acquisition
This section describes how functional programming skills mature through experimentation and why using a new skill too eagerly in production can be harmful.
- Skill acquisition curve: Describe how a new functional programming skill develops from enthusiastic use through failed experiments to a better sense of when to use it and when not to.
Why it matters: Missteps are part of developing judgment, not proof that the skill has failed. - Premature production application: Explain why applying a newly learned skill too eagerly in production code can be risky.
Why it matters: It helps you avoid making production code harder to work with while you are still learning.
Key terms: skill acquisition, mastery, production code, readability, maintenance
19.5 Parallel tracks to mastery
This section proposes parallel sandbox and production tracks for practicing functional skills while judging when each skill is ready for real-world use.
- Parallel tracks for mastery: Explain why developing skills need both a sandbox for experimentation and a production track for careful application.
Why it matters: You can keep practicing enthusiastically without making important code bear the cost of an unpolished skill. - Skill-by-skill production readiness: Describe how to decide which skills belong in a sandbox and which are ready for production, and how production use contributes to mastery.
Why it matters: Assessing each skill separately lets you practice what is new while refining what is ready in real projects.
Key terms: two-track model, Sandbox, Production, mastery, refinement and judgment
19.6 Sandbox: Start a side project
This section gives four criteria for choosing a side project that makes practicing new skills manageable and enjoyable.
- Small and playful project scope: Explain why a side project should start small and be whimsical: a small scope makes progress achievable, while playfulness leaves room to explore and change direction without worrying about failure.
Why it matters: A project that feels achievable and fun is easier to keep using for practice. - Focused practice on expandable foundations: Describe how to choose a project built with familiar skills, practice one new skill on top of them, and leave basic features that can be expanded later.
Why it matters: Using a familiar foundation keeps the practice focused while leaving room to grow.
Key terms: side project, whimsical, familiar skills, one new skill, stable foundation
19.7 Sandbox: Practice exercises
This section recommends short, low-stakes exercises for practicing functional programming skills in different ways and under practical constraints.
- Low-stakes exercise practice: Explain why isolated exercises are useful for practicing functional programming skills.
Why it matters: A small, low-stakes problem lets you concentrate on a skill rather than a project's risks. - Multiple approaches to one problem: Describe how solving the same exercise in different ways can develop functional programming skills.
Why it matters: Repeating a familiar problem gives you room to try new approaches and practice your workflow. - Practical limits in challenges: Explain how demanding programming challenges can make functional programming skills practical rather than merely theoretical.
Why it matters: A solution that works on a tiny input may need rethinking when real resource limits appear.
Key terms: isolated exercise, sandbox, Code Katas, different skills, testing, Project Euler, memory limitations, performance limitations, stack size limitations
19.8 Production: Eliminate a bug today
This section recommends two small, practical ways to eliminate bugs in an existing codebase: remove a global mutable variable or fix a problematic timeline.
- Removing one global mutable variable: Explain why removing a global mutable variable can prevent bugs, and describe how to tackle one in an existing codebase.
Why it matters: Removing even one source of shared mutable state can be a useful improvement without overhauling the codebase. - Fixing one problematic timeline: Describe how to use a timeline diagram to investigate a suspected race condition and eliminate an unwanted ordering.
Why it matters: Investigating one familiar ordering bug gives you a manageable way to improve production code today.
Key terms: global mutable variables, implicit inputs and outputs, timeline diagrams, race conditions, isolating, sharing, and coordinating, undesirable orderings
19.9 Production: Incrementally improve the design
The section shows how small changes to production code can gradually improve its functional design.
- Incremental design improvements: Explain why improving production code one small step at a time is worthwhile, even when the benefits are not immediately visible.
Why it matters: You can improve the design of code you use today without waiting for a wholesale rewrite. - Logic extracted from actions: Describe how to improve an action with a lot of logic without trying to eliminate the action itself.
Why it matters: This gives you a manageable improvement to make even when an action cannot go away. - Explicit action inputs and outputs: Explain how changing one implicit input or output to an explicit one improves an action.
Why it matters: You can reduce an action’s dependence on surrounding state without needing to remove every dependency at once. - Functional replacements for loops: Describe how replacing individual for loops with functional tools contributes to an incremental shift in style.
Why it matters: A single loop is a practical place to start changing the style of production code.
Key terms: incremental, design, action, calculation, extract, implicit input, implicit output, explicit, coupled, for loops
19.10 Popular functional languages
This section presents popular functional languages as practical choices and gives brief examples of how they differ.
- Practical functional language choices: Explain why the listed functional languages are presented as practical general-purpose choices.
Why it matters: You can choose among these languages without treating one as the only practical option. - Differences among listed languages: Describe concrete differences among at least two listed languages, such as their platforms, applications, or stated design characteristics.
Why it matters: The brief descriptions give you starting points for comparing languages by what they run on or are used for.
Key terms: functional languages, libraries, general-purpose programming language, ClojureScript, Java Virtual Machine, actors, fault tolerance, statically typed
19.11 Functional languages with the most jobs
This section recommends functional languages to learn when job opportunities are the main goal.
- Job-oriented language choices: Explain which functional languages the section recommends for job seekers and how it distinguishes the two groups by available opportunities.
Why it matters: It gives you a way to weigh employment prospects when choosing a language to learn.
Key terms: Elixir, Kotlin, Swift, Scala, Rust, Clojure
19.12 Functional languages by platform
This section groups functional languages by the platforms they can target.
- Functional languages by platform: Describe how the section groups functional languages for browsers, web backends, mobile apps, and embedded devices, giving examples of the available languages or routes for each.
Why it matters: The platform you need to support can narrow which functional languages are practical choices.
Key terms: platform, Browser (JavaScript engine), Web backend, Mobile (iOS and Android), Embedded devices
19.13 Functional languages by learning opportunity
This section helps readers choose a functional language to explore based on what its prominent features can teach them.
- Type systems as design guides: Explain why someone interested in static typing might choose a functional language to learn from, and name an example from the section.
Why it matters: A language’s type system can be a learning environment for better design decisions. - Data transformation language style: Describe what distinguishes the listed data-transformation languages and give an example.
Why it matters: This style offers a focused way to practice transforming data with functional tools. - Concurrency learning approaches: Distinguish the three approaches used to organize the section’s concurrency-focused languages, with an example of each.
Why it matters: The grouping points to different language features you could study to improve your understanding of concurrency.
Key terms: static typing, type systems, functional tools, data transformation, concurrency primitives, actor model, type system, multiple timelines
19.14 Get mathy
Introduces several mathematical ideas behind functional programming and briefly describes how they relate to functions, types, and effects.
- Lambda calculus and combinators: Explain that lambda calculus includes function definitions and calls, and that combinators are functions that modify and combine other functions.
Why it matters: These ideas show one mathematical source of functional programming’s emphasis on functions. - Type theory and static types: Describe type theory as logic applied to code, concerned with what can be derived and proven without inconsistency, and state its connection to static type systems in functional languages.
Why it matters: It connects a familiar programming feature—static types—to the mathematical ideas behind it. - Category theory and effect systems: Describe category theory’s focus on structural similarities between types and explain, at the section’s high level, how effect systems use concepts borrowed from it to model actions with immutable data.
Why it matters: This illustrates how mathematical ideas can inform software design and approaches to side effects.
Key terms: lambda calculus, combinators, type theory, static type systems, category theory, effect systems, monad, applicative functor, immutable data
19.15 Further reading
The section recommends further reading for different functional-programming interests and encourages readers to explore books for their chosen languages.
- Further reading by interest: Distinguish the four recommended books by the kind of functional-programming learning each offers.
Why it matters: The distinctions can help you choose a book that fits what you want to learn next. - Language-specific reading options: Describe the additional recommendation for finding functional-programming books related to languages you use or want to use.
Why it matters: You can continue learning functional programming in a language relevant to your own work or interests.
Key terms: Functional-Light JavaScript, Domain Modeling Made Functional, Structure and Interpretation of Computer Programs, Grokking Functional Programming, functional programming, functional languages
19.16 Conclusion
The conclusion encourages readers to apply the functional programming skills they have learned, keep practicing, and explore further learning when ready.
19.17 Summary
19.18 Up next…
Concepts explained in this chapter
- functional, stateless philosophyA programming paradigm that emphasizes composing computations as evaluations of functions while minimizing mutable state and side effects.
- actionAn action is a computation whose observable result depends on when or how it is performed and may involve effects beyond producing a value.
- mathematical calculationA calculation is a category of code that deterministically computes a result from its inputs without directly interacting with the outside world.
- distributed systemA software system whose components communicate over a network and may experience delayed, reordered, duplicated, or lost messages.
- immutable collectionData or state whose represented values cannot be modified after creation.
- loopAn iteration construct that repeatedly executes a block while progressing through a sequence or range of values.
- implicit inputAn input obtained by a computation from surrounding state or context rather than supplied explicitly as a function argument.
- dataAn inert representation of information that requires interpretation to acquire meaning and can be stored or transmitted.
- higher-order functionA function that accepts functions as arguments, returns functions as results, or otherwise treats functions as values.
- static typingA type system that checks and constrains the types of program expressions before execution.
- implicit outputAn effect of a function that changes external state or performs an observable operation rather than returning the result directly.
- global variableA variable whose binding is accessible across broad program or module scope rather than being confined to a single function or block.
- refactoringThe systematic restructuring of existing code without changing its externally observable behavior.
- reactive architectureA software architecture pattern centered on asynchronous communication and systems that respond to changing events or conditions.
- stratified designAn architectural pattern that organizes software into layers ordered from relatively stable foundations to more frequently changing elements.
- concurrency primitiveA synchronization construct that provides a defined operation for coordinating concurrent execution paths or managing shared resources.
- parallelismExecution in which multiple actions may occur simultaneously or without a fixed order relative to one another.
- sequential processingA sequential action is an action that is ordered to occur in sequence with other actions on the same execution timeline.
- code readabilityThe degree to which source code can be understood by human readers.
These guides are generated from the text of Manning books by Manning's knowledge graph and link to the sections they draw on. The full books are available on liveBook and at manning.com.
