An intro to Functional Programming in JavaScript~ (and React and/or Vue)

Bonus Note: patterns described here should be applicable in React, Vue, Angular, and really any other programming language where the main focus is data or a user — while actions and events are involved. Imagine for a moment, if something is going from somewhere-to-somewhere, we can start to sample ideas from Mathematics and Physics. We can create well-characterized patterns to solve well-characterized scenarios, and we can also discover interesting patterns.

Functions can act as labels… labels of function throughout your application. Sometimes people label too much and create a lot of granular functions. It is important to note that the inlet and outlet of each function represent a jump in dimension. Abstraction can cause confusion when paired with granularity because you might be comparing two functions not directly connected together; you also lose some freedom of access to local data if you move upstream.

Fig 1.0 — Dimensions
Fig 1.1 — Some kind of inter-dimensional movement
Fig 1.3 — Waterslides with data as humans

fn(name) = (name + bold)

Fig 1.4 — The slope of the tangent is 0 at the vertex
const isBold = (name.bold === true);

Predicates: we don’t want to care when it actually is true or false, we just want to set it up so that it will definitely change at the correct moment in time when some specific criterion(s) are true. This is a low-key form of decoupling things that matter from things that don’t matter.

const phoneNumberOfDavid = '555-123-4576';if (isBold) await call(phoneNumberOfDavid);

If functions always move downstream over time, you can write out on a piece of paper the series of functions (actions maybe) that kick off during an event, and you can quickly start to understand what you need to know to modify the series of functions. You can ask yourself: what data is involved, where is it coming from, where is it going to, and why?

There will be smaller details, but you need to establish the branches of a tree before you can draw leaves, unless you assemble the tree asynchronously, but you will always start and finish drawing the tree.

import FibonacciAdapter from 'some-outlet-right-now';const makeLeafOnBranch = (data) => {
const scalingFactor = 1.618;
return FibbonacciAdapter({
action: 'ADD-LEAF',
someRatio: scalingFactor,
someData: data,
});
};
const drawLeaf = data => makeLeafOnBranch(data);const drawBranch = drawLeaf => drawLeaf();drawBranch(data => drawLeaf(data));

Keep this in mind: the penalty of the wrong abstraction is worse than the penalty of no abstraction.

const d = a => (a + b + c);
function d(a) {
const startPlusCrap = a;
startPlusCrap += b; startPlusCrap += c; return startPlusCrap;
}

In my opinion, an Array named filteredData is generally not as good as one named filteredCountries or countriesFilteredByDate because it can make a huge difference depending where and how you see it being used inside other things. While you’re scanning code, you don’t want to be wondering things like “wtf is filtered data?”. filteredData reads more like a more verbose version of x. It’s not an exact science. Pay close attention when you have to start opening other files to see what something is. Well-chosen names can help protect against that confirmation step.

DATA FLOW

Functional Reactive Programming is all about thinking in data flows over time.

Fig 1.4 — Functional Reactive Programming (FRP)
Fig 1.5 — Directed Acyclic Graph (DAG)
render(
<App />,
document.getElementById('root'),
)

Remember: we must first discuss a bunch of crap related to weather and climate before we start talking about the Aerodynamics of Wind Movement. Wind is the movement of air from an area of higher pressure to lower pressure. There is a pressure gradient force. The sharper the drop in pressure, the faster the wind measured. Data flows exactly like this — only way different. We have to wander into a bit of complexity before we can simplify it.

The internet is a series of tubes, and so is your app.

PART ONE — THE IMPORTANT THEORIES

Fig 2.0 — Bob Nyegers: he paints nice logic in your neighbourhood.

In JavaScript, things flow the best over time immutably and unidirectionally. Why? Because of live references and dynamic typing.

Fig 2.1 — Mousetrap Board Game

Note: forget about deterministic transformations for now. Your brain may catch on fire. I only mention it for the guy with the beard and his coffee. Let’s also note the gender-specific reference here and always be mindful to include females and non-binary individuals — they can also code great if they choose to.

Deterministic means, “if you put in the same input, you get the same output 100% of the time.”

Slow down: It’s understandable if that doesn’t fully make sense. To understand more, you will need to research the JavaScript event loop which has a call stack, function queue, and the heap. The call stack is single threaded, so you can only process one function at a time, but the good news is you can load up an infinite number of functions in the queue and they will complete as fast as they can according to laws of Mathematics and order of operations.

Fig 2.2 — Pass-by-reference vs. pass-by-value
const sandwich = {
flavour: { confirmed: 'pretty good' },
isTasty: getFlavour(sandwich.flavour),
}
Fig 2.3 — Look at this as if it were a single object that doubles as a function too

Where this becomes dangerous is real-time pass-by-reference analysis.

Advanced Note: This is also rule number 1337 for function composition. You can’t create a series of events and “set your clock to it” if you change the third step to modify the clock’s time by a random amount 50% of the time. That sounds weird and it produces unreliable results. It’s not mathematical, and you don’t want it in your app… unless you’re working on TrollCalculator.exe.

Immutability can free you from trying to predict the future and recount the past. Who cares where we came from or how we got here. We care where we are going next and how we are going to get there.

const config = {
title: 'Sandwiches can produce good flavour',
author: 'Alice Bobson',
timestamp: 128364096092,
}
const renderArticle (config) => {
return (
<div>
<h1>{config.title}</h1>
<h3>{config.author}</h3>
<span>Created: {Date(config.timestamp)}</span>
</div>
)
}
renderArticle(config)
const config = {
title: 'Sandwiches can produce good flavour',
author: 'Alice Bobson',
timestamp: 128364096092,
content: 'Today, we added one key to an object, and we found that
our code was easy to test, extend, and maintain.',
}
const renderArticle (config) => {
return (
<div>
<h1>{config.title}</h1>
<h3>{config.author}</h3>
<span>Created: {Date(config.timestamp)}</span>
<div>{config.content}</div>
</div>
)
}
renderArticle(config)
const user = {
firstName: 'Alice',
lastName: 'Bobson',
}
// We just learned Alice's age. We need to add it.const userWithAge = {
...user,
age: 1337,
}
return userWithAge

Note: if you need to research the spread operator, then go ahead and load up another browser tab for that. That’s the ... symbol above.

const fn = x => ({ x })

Remember, the shortest, most concise possible code isn’t always the simplest to understand.

Fig 2.4 — Ronco Food Dehydrator
Fig 2.5 — Depiction of the JavaScript heap without Garbage Collection

In JavaScript, the execution context is usually a function being executed.

const garbage = () => {
// when you stop referring to me, I will be gone
return 'cool'
}
const generateGarbage = () => {
const createReference = garbage()
if (createReference === 'cool') {
// perform some work
}
// as soon as we arrive here during code execution,
// JavaScript unloads `garbage` from memory
return 'that is very cool'
}

General Rule Note: As soon as you know you no longer need a reference, ask yourself, is this going to get garbage collected now? Your goal is to notice when the answer is no. This is how you avoid memory leaks. It is a key JavaScript skill.

Garbage Note: Garbage Collection is cheap. It’s so cheap, we don’t really care about its cost until our JavaScript problems become more serious than “what is functional programming?”. We don’t care too much about premature optimization. StackOverflow.com will help as soon as you describe a Garbage Collection-related problem.

I’ve hidden a secret puzzle in the bolded words above.

Function Composition

A deterministic function produces the same output when it is given the same input.

const ok = 33const getNumber = num => num // returns 33 if you input 33const correctAnswer = 1 + getNumber(ok) + 7console.log(correctAnswer) // returns 41
Fig 3.0 — Function composition

Brain Helper Note: g feeds into f and both are deterministic.

f(g())

What if we used equational reasoning and said that function = equation?

const locationX = 'http://www.com/profile.html'const config = {
name: getProfile('Reader McGee').name,
start: '1337.html',
end: () => next(locationX),
error: () => next('404.html'),
}
// destructuring not used in order to show correlations
const goToLocation = (config) => {
if (config.start !== '1337.html') {
return config.error()
}
return config.end()
}
goToLocation(config)

Where it is going = What is returned

if (today === 'monday') use('multiplication')
if (today === 'friday') use('division')
const users = getNumberOfUsers()
Fig 3.1 — Gottfried Wilhelm Leibniz

Quick Research: https://en.wikipedia.org/wiki/Gottfried_Wilhelm_Leibniz

My brain, Gottfried! WTF were you doing in the year 1700 AD?? Is this real life??

Fig 3.2 — Luckily, I don’t need to do this in JavaScript

Conclusion

--

--

I prefer to work near ES6+, node.js, microservices, Neo4j, React, React Native; I compose functions and avoid classes unless private state is desired.

Love podcasts or audiobooks? Learn on the go with our new app.

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store