Click here to Skip to main content
14,580,263 members

Functional Programming – You Probably Already Know It!

Rate this:
4.10 (15 votes)
Please Sign up or sign in to vote.
4.10 (15 votes)
1 Jul 2020CPOL
Common concepts in functional programming language
In this post, we’ll explore common concepts in a functional programming language in TypeScript.

Functional programming as a concept has been around for years. But in the last 5-6 years, somehow, it has become the popular kid on the block.

Most of the folks I’ve talked with in recent years have been intimidated by functional programming, and specifically the popular languages, like, Scala, Erlang, Haskel, etc.

Well, my (official) introduction to functional programming was with Scala, and since I was used to verbose OO languages like C#, Java or JavaScript, Scala’s programming style required some time to get used to.
But, one thing that didn’t take getting used to, was functional programming.

What I didn’t realize was, that, since I had been coding in JavaScript/TypeScript for a few years now, I already knew a lot about typical functional programming concepts (like functions being first-class citizens, high-order functions, closures, etc).

Considering the statistic on stackoverflow, if you are developer, then there’s a 67.8% probability you already know functional programming. JavaScript has been the most popular programming language for the seventh year in a row now.

When it comes to top functional programming languages, JavaScript/TypeScript would, at best, get an honorable mention. But believe me, with the introduction of ES6 and evolution of TypeScript, it already supports a lot of functional programming concepts.
And if you’ve been coding in JavaScript/TypeScript for a few years now, you are (almost) a functional programming wizard.

So, what are some of the common concepts in a functional programming language:

  1. Functions as first-class citizens and higher-order functions
  2. Pure Functions
  3. Closures
  4. Currying
  5. (Tail) Recursion
  6. Immutability

We’ll try to explore at all these concepts in TypeScript in the following sections.

Functions as First-Class Citizens and Higher-Order Functions

First-class citizens: When we say functions are first-class citizens, it means, you can assign function to variables, pass them as arguments and have them as return types.

let funcAdd = (a: number, b: number): number => {
    return a + b;
}
console.log(funcAdd(5, 4)); // 9

High-order functions: A function is called high-order, when it can accept one or more functions as parameters or if it’s return type is function.

type paramFunc = (k: string) => number;
function higherFunc(fn: paramFunc, arr: string[]): number[] {
    let returnArray: number[] = []
    arr.forEach(elem => {
        returnArray.push(fn(elem));
    });
    return returnArray;
}

let lengthFunc = function (param: string): number {
    return param.length;
}

console.log(higherFunc(lengthFunc, ["hello", "bye"])); // Array(2) [5, 3]

Pure Functions

  • Pure Functions are methods which do not alter any external state, for example, any class level variable, external DB, file, etc.
  • Also, any external factors (like, time of the day) shouldn’t influence their behavior.
  • A pure function should always return the same output for the same set of inputs.
// Impure Function

var impureFunc = (): number => {
    return new Date().getMonth();
}
// Will return the numeric month depending on when you run it
console.log(impureFunc()); 

// Pure Function
var funcAdd = (a: number, b: number): number => {
    return a + b;
}
// Will always return output consistent with input
console.log(funcAdd(5, 4)); 

Closures

Closures are one of the cooler concepts in programming. Although they could lead to difficult to debug issues, but once you get the hang of it, you’ll love them.

Closures basically store the state of outside data in the function. If, at the time the function is compiled, it has a reference to a global (or parent function level) variable, it would continue to hold its value even when the parent function containing the variable goes out of scope (or has closed).

var timerFunc = (name: string) => {
    let functionVar = `Hello ${name}`;
    setTimeout(() => {
        console.log(`after 1000 ms - ${functionVar}`);
    }, 1000);
    console.log("exiting timerFunc");
}

timerFunc("chinmoy");

// exiting timerFunc
// after 1000 ms - Hello chinmoy

As you can see from the above example, although the timeFunc exited, the functionVar parameter’s value was still retained inside the function closure (cool right). Hence, when the timeout elapsed, they could still print the value of functionVar.

Currying

Currying is a very popular functional programming concept. Every language has a different flavor for currying (pun not intended), but TypeScript probably has the most bland flavor (pun intended ;)) of all.

It is basically a technique to construct functions that allows for partial application of the function’s arguments. What it basically means is, you can either call a curried function with all its parameters, or you could call the function with limited parameters and it would return a function which accepts the rest of the parameters.

function curryAdd(a: number): (b: number) => number {
    return (b: number): number => a + b;
}

// Partial application of the function
let moreAdd10 = curryAdd(10);

console.log(moreAdd10(3)); // 13
console.log(curryAdd(3)(10)); // 13

(Tail) Recursion

It’s a very popular opinion that functional programming favors recursion v/s looping. Well, although recursion is fancy and results is concise code, it can incur performance losses, since the results of every recursion are stored on a stack.

Hence, most functional programming languages favor something known as Tail Recursion.

Let’s looks at the most trivial sample code for recursion. Getting factorial of a number:

// Snippet for Normal Recursion
let factFunc = (param: number): number =>
    param== 0 ? 1 : param* factFunc (param- 1);

console.log(factFunc (10)); // 3628800


// Snippet for Tail Recursion
const factFuncTail = (param: number): number => fact(1, param);

const fact = (accum: number, val: number): number =>
    val == 1 ? accum : fact(accum * val, val - 1);

console.log(factFuncTail(10)); // 3628800

I found the tail recursion function a little difficult to understand but for engines optimized for tail recursion, it performs on par with looping.

Unfortunately, not all JavaScript engines are optimized for tail recursion, so you might incur performance penalties when writing recursive code in JavaScript/TypeScript.

Immutability

It’s one of the core best pratices when writing functional code. One should always strive to use immutable data types. Having these results in more robust and reliable code which is easier to debug.

Unfortunately, TypeScript doesn’t provide strictly immutable data structure. We have a notion of Immutability when using “const”, but these are not strictly immutable.

Let me show you what I’m talking about:

const cStr = "Hello, I am Immutable";
cstr = "Trying to mutate here"; // This will produce an error

const lst = ["A", "B", "C", "D"];
list = ["X", "Y"];              // This will produce an error

list.push("X"); // This will compile and run just fine (Not immutable after all, huh!)

There are a few other characteristics of functional programming languages, but the core idea which I’m trying to convey is that if you have experience coding in JavaScript/TypeScript, you already know functional programming.

Of course, this doesn’t mean there wouldn’t be a learning curve when learning a language like Scala, but, I believe it’ll not be very steep.

Happy coding!!

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)

Share

About the Author

Chinmoy Mohanty
Software Developer
United States United States
I am a Developer working across multiple Technologies like .NET, Scala, Angular and NodeJS.
Passionate about WEB technologies more than anything.
Fascinated about the idea of how the WEB world and the WinForm world are slowly merging into each other, with a very thin line to differentiate them.

I am an active blogger and I blog mostly about Technology. Also, I have presented at certain points in the past on technical topics.

My Blog


Life & Tech

Programming Community Profiles


Stack Overflow
GitHub

Presentations


Slideshare

Social Profiles


Facebook | Twitter | LinkedIn | Google+

Comments and Discussions

 
GeneralMy vote of 5 Pin
Member 1487764730-Jun-20 17:50
MemberMember 1487764730-Jun-20 17:50 
QuestionRepeated paragtaph Pin
Member 1276350124-Jun-20 2:34
MemberMember 1276350124-Jun-20 2:34 
AnswerRe: Repeated paragtaph Pin
Chinmoy Mohanty25-Jun-20 6:58
MemberChinmoy Mohanty25-Jun-20 6:58 
GeneralRe: Repeated paragtaph Pin
Member 1276350125-Jun-20 7:32
MemberMember 1276350125-Jun-20 7:32 
QuestionTail recursion in a non-FP language... Pin
Marc Clifton23-Jun-20 2:46
mvaMarc Clifton23-Jun-20 2:46 
AnswerRe: Tail recursion in a non-FP language... Pin
Chinmoy Mohanty23-Jun-20 3:06
MemberChinmoy Mohanty23-Jun-20 3:06 
QuestionMessage Closed Pin
22-Jun-20 23:05
Memberthuonghailongvan22-Jun-20 23:05 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.

Technical Blog
Posted 22 Jun 2020

Stats

8.7K views
7 bookmarked