# Is the JavaScript code I've provided following Functional Programming best-practices?

I'm trying to wrap my head around JavaScript Functional Programming.

I have created a very basic script that creates a new elements and appends them to the DOM.

If anyone could share any feedback, or great resources on the subject, that would be awesome.

Where does this style of programming lend itself best? Web Development, or more Software development? I understand that React uses this coding paradigm. I'm actually very comfortable using React - but, I'm wondering how it might be best utilised with vanilla JavaScript

Thanks!


// create a button that accepts text and a callback function

const createButton = (text, func) => {
const button = document.createElement('button');
const buttonText = document.createTextNode(text);
button.appendChild(buttonText);

return func();
});

return button;
};

// create paragraph tag that accepts a text arg

const createText = (text) => {
const pTag = document.createElement('p');
const pTagText = document.createTextNode(text);
pTag.appendChild(pTagText);

return pTag;
};

// pure functions

const myList = [1, 2, 3];

const sayHello = (name) => {
};
// can be
const sayHello = name => Hello ${name}!;  and const addNums = (x, y) => { return x + y; }; // can be const add = (x, y) => x + y;  # 💡 Tip 2: Spice up your functions But then what is the purpose of the lambda notation, and why is your code defeating its purpose? To put it simply: a lambda is a function that takes zero or one argument(s), maybe transforms it, and yields a result. Wikipedia's article about lambda calculus says the same, but with more jargon: [...] all functions in the lambda calculus are anonymous functions, having no names. They only accept one input variable, with currying used to implement functions with several variables. You use a lot of functions as procedures (sequence of steps) which you cannot have in FP, and you are using multiple parameter functions which are also disallowed (or rather just do not exist in FP). But, you might ask, how are you supposed to do anything with just one parameter and a single expression body? Let us take a snippet of your code and refactor it into a nice functional style: // Original const createButton = (text, func) => { const button = document.createElement('button'); const buttonText = document.createTextNode(text); button.appendChild(buttonText); button.addEventListener('click', () => { return func(); }); return button; };  // Functional alternative // Some setup, notice the currying for multiple arguments. const text = text => document.createTextNode(text); const newButton = () => document.createElement("button"); const listen = event => handler => target => { // Javascript was not meant to be used purely functionally, // so we have to use a block with several statements to // mutate the target, and then return it (mutation will never // happen in functional programming, as you might know). target.addEventListener(event, handler); return target; }; const append = child => target => { // Same story: we have to return the target after mutating it. target.append(child); return target; }; // Here comes the true power of functional programming: composition const onClick = listen("click"); const addLabel = label => append(text(label)); const sayHi = () => console.log("Hi!"); const sayBye = () => console.log("Bye."); const button = label => handler => addLabel(label)( onClick(handler)( newButton())); const friendlyButton = button(":)")(sayHi); const sadButton = button(":(")(sayBye); // Try it out! document.body.append(friendlyButton, sadButton);  Ok, giant code sample with weird and maybe hideous things. Let me explain it! Firstly I would like to say that Javascript is a great language, but the DOM is not the best part to use FP for, because it's an amalgamation of mutation and imperativeness, which are the arch-enemies of FP. But let us do it anyways because it is fun! The first statement of the refactor goes as follows: const text = text => document.createTextNode(text);  which is essentially a function that, when called with an argument text will create a textNode with text being its text. Now this is a bit of a weird one, because we made a function that takes an argument, and then calls another function with that very argument, so we basically aliased it. Aliasing is the same as storing it in a variable with another name, so why not write it like this: const text = document.createTextNode;  text is equal to document.createTextNode, so text("Hi!") is equal to document.createTextNode("Hi!"). Now JS is a bit weird (and full of side-effects), so we have to specify that the this of document.createElement is document (document.createElement.bind(document)). The peculiarities of Javascript's this go far beyond the purpose of this post so if you do not understand what that meant, just wrap it in a function like so: x => y(x); The first real weirdness happens in the listen function: const listen = event => handler => target => { /*...*/ };  What? A function that returns a function that returns a function that returns something else?! Yep, that is functional programming baby! But why would we do this? Because it allows for very easy composition. Notice how later on, we defined the function onClick, which is a composed listen: const onClick = listen("click"); // This means the following: const onClick = handler => target => target.addEventListener("click", handler);  So we made a function that always adds a click eventlistener to a target. We can take this a step further: // Let's make a function that makes an element yell "OUCH!" on click! const ouch = onClick(() => console.log("OUCH!")); // This means the following: const ouch = target => target.addEventListener("click", () => console.log("OUCH!")); // Try it out! const boxingDummy = ouch(addLabel("Don't hit me!")(newButton())); document.body.append(boxingDummy);  I hope that made it clear why you would write programs in such a weird (coming from procedural programming) way. I would link you the wiki article but that is just unintelligble jibberish to me too. # 💡 Tip 3: Lose control You seem to really rely on the imperativeness of Javascript to perform tasks in a set order, which does not fit well in a functional style -- most functional languages do not even allow it. The great functional programming evangelists have thought about this long and hard, and showed us how you do not need loops, if's or sequences to create complete and functional (in the literal sense) programs. Taking, for example, another function you wrote: const view = () => { const component = document.createElement('div'); // create a button element that has a callback function that will append the returned value to the DOM component.appendChild(createButton('Hello', () => { return component.appendChild( createText( sayHello('Kristian') ) ); })); component.appendChild(createButton('Add Numbers', () => { return component.appendChild( createText( addNums(3, 7) ) ); })); component.appendChild( createButton('Log', simpleLog) ); component.appendChild(createButton('Add to array', () => { console.log( Original array: [${myList}] - New array: [\${addToArray(4)}]);
}));

return component;
};


Pardon the joke, but this looks really WET... (as in, the opposite of DRY). You call component.appendChild(createButton(/*...*/)) a lot of times. Apart from that being a bit of a code smell, it also is a really great place to put in some FP magic. Analysing the abstract meaning of your code, let me write that out in a more functional style:

// Remember our previous functions?
// I made them nice and generic so they are
// reusable here!
const appendButton = label => action => append(button(label)(action));
const add = x => y => x + y;
const saySix = () => console.log(addFive(1));
const fold = (...functions) => value => functions.reduce(
(result, fun) => fun(result),
value);
const component = document.createElement("div");
const view = fold(
appendButton("Greet")(sayHi),
appendButton("What's five plus one?")(saySix)
/* etc... */);

// Try it out!
document.body.append(view(component));


BAM! No blocks, no loops, no if's! Instead of a sequence of statements, we use a fold to abstract away a lot of the DOM boilerplate. Higher-order functions such as fold(left) are very important functions to keep in your arsenal. I suggest reading up on it a bit, if the article isn't too crytographic (there's a joke that says functional programmers tend to lose their ability to explain FP as soon as they understand, and I think that applies perfectly on most wiki pages).

Well that should be about it. To summarise:
• Javascript DOM isn't the best place to apply FP (in my humble opinion), but go ahead and break the rules!
• Don't get RSI: (x) => { return y; } is the same as x => y.
• Procedures are so 1970; compose a function from functions to solve your problems (and most importantly: be able to reason about your solution).
• Currying and higher-order functions are a functional programmer's best friends, conquer the world with them.
• Sometimes there is a wonderful interplay of the right question at the right time and the perfect balance of motivation and expertise of the respondent. This, what happens here, is a great example of such an interplay. Absolutely blown-away by your answer. Never even heard of Functional Programming and your answer just clicked. In my world there was Object-Oriented Programming and Procedural Programming. With the former being the "best" way. Where do you even start to understand programming on that level? With higher-order functions and currying? – Melvin Idema Apr 30 at 23:12
• @MelvinIdema Thanks for the kind words. I was displeased by all of my imperative code because it didn't have the expressive power I wanted. I figured I couldn't be alone in thinking so. I quickly fell into a rabbit hole of computer science, and I just happened to come out of it having seen the light. To me, everything is composition. Subatomic particles make atoms, atoms make cells, cells make organs, organs make organisms... As I understand the world, everything is a function of smaller functions. Functional programming to me is the only next step in programming. – Maanlamp May 1 at 9:46