Functional Programming, Functions, and Currying Functions: Behold Beauty!

This post is going to be about functions, currying functions, and how pleasing it is to do so. Recently I’ve been focusing on javascript fundamentals and learning me some functional programming.

Everything I’ve seen or read about in true functional programming (not React folks, I’m talking like Clojure and Haskel 😎) has made my used-to-be-math-teacher-senses tingle in the best way. It’s been so pleasing that I’d like to try to convince some to use functional principles more.

So let’s take a look at what currying is and some examples.

Wait, functional programming?

Yeah, so I’ll describe as much as I think I understand.

Caveat emptor: I am no expert at functional paradigms. I am simply a former math teacher who is distilling what he thinks he understands thus far. Hopefully this will be edifying for you! 😄

In the math world functions are a thing. They follow one rule: A function has only one output for any given input.

If you give one particular thing to a function, you should get only one particular result out. So, if you get multiple results out of a function it’s not really a function, you’d call that bad boy a “relation.” But let’s not talk about those.

In functional programming, we’ll try to keep our functions “pure”.

Pure functions

In the case of pure functions the one particular result you get from the one particular input should be the same result no matter what time or place or computer or class or website or server you call it on. So for example, this function is incredibly un-pure:

function getTheTime() {
    return Date.now();
}

Hey, it’s a function because it only gives you one result! However, it’s never going to give you the same answer if you call it again, unless you fudge a computer clock for some reason.

You might say, “Well, of course, you contrived that to be impure.”

Yes, yes I did. But here’s another that you see all the time.

const thing = document.querySelector('.some-class');
// And that goes for any vanilla js query functions

What’s the result? Could be an element… also could be null. Who knows? Depends on where you call it and when you call it.

(So you might say that this is hopeless to try to not use querySelector, and I think you’re right. In the end, we have to use some impure stuff to get things done, and so think of these things more as “guidelines” that will guide you to coding nirvana.)

Pure functions also don’t cause side effects

So, part of the reason we want the pure functions is dependability. If functions cause things to change in a program, this can lead to sadness- especially if you didn’t anticipate the changes. Like this:

function getArrayRange(arr, first, last) {
    return arr.splice(first, last - first);
}

const array = [1,2,3,4,5];

const subArray = getArrayRange(array, 0, 2);
// subArray = [1,2]
// array now is [3,4,5]!

It snuck in there. You actually changed the array. The old array no longer has those elements, and this could be a very easy thing to do accidentally!

(And yes, you can just use slice so that you get a shallow copy, but this illustrative of the kind of issue that happens a lot.)

This is the impetus for immutable.js and why you should always send a new array/object to replace state in React.

Let’s get back to currying…

Currying is a way of changing a function that takes multiple arguments, and breaking up that function into a series of functions each with a single argument.

*Cue classic add example*

// multiple argument function
const addMulti = (x,y) => x + y;

// Shiny curried function
const add = (x) => (y) => x + y;

In currying you find yourself making a function with one argument return another function with one argument, and so on and so on instead of making one function that takes many arguments.

With addMulti you would execute addMulti(2,3). With add you would have to execute add(2)(3). Why? When you do just add(2), it returns the function (y) => 2 + y. Doing only part of a function at a time is called partial application, and currying I think makes this easier. So after fixing 2 to be x, the 3 is being put into this new function, and 5 comes out.

So, you could make all sorts of extended functions of this one general one.

const addTwelve = add(12);

addTwelve(50) // 62

Which, by the way, this isn’t unique to currying. You can do this with mult-argument functions. It’s just not as pretty. Take a look below at the alternative partial application, and I think you’ll agree that currying makes things so readable.

const addTwelve = (x) => addMulti(12,x);

addTwelve(50) // 62

So why curry?

It’s so easy to compose things! Let’s do another example:

const addStyle = (property) => (value) => (element) => {
    element.style[property] = value;
}

const backgroundOrange = addStyle('background')('orange');

backgroundOrange(someDiv);

Okay, so that’s kind of cool. But you could do that by just directly setting the style on that someDiv right? Yes, but this function can be used anywhere for any css properties. I now have an avenue to make all sorts of “styling functions.”

Also, these functions work better in mapping/piping situations. For example:

// "non-functional way"
someCollection.forEach(el => {
    el.setAttribute('disabled', false);
});

// The currying way™
const setAttribute = (name) => (value) => (element) => {
    element.setAttribute(name, value);
}

const enable = setAttribute('disabled')(false);

someCollection.forEach(enable);

Yes, the first example here is smaller. But I love the readability of the curried example. I’ve also separated my concerns by not tying the setAttribute thing to those elements in that collection!

Another pretty example

I was recently doing a mini code challenge- the type you expect to see in an interview. The challenge was to create a right-justified character “stairway” like this:

   #
  ##
 ###
####

Now, the function accepts how many steps (above is 4), and your program has to output the string.

Here was my first implementation without focusing on functional stuffs.

function createGrid(n) {
  return new Array(n)
    .fill(new Array(n).fill('x'));
}

function removeDiagonal(arrayOfArrays) {
  return arrayOfArrays.map((row,y) => {
    return row.map((col,x) => {
      return (arrayOfArrays.length - y - 1) <= x ? "#" : " " ;
    })
  })
}

const grid = createGrid(5); // Or whatever they ask us to do
const diagonalRemoved = removeDiagonal(grid);
const view = diagonalRemoved.map(row => row.join("")).join("\n");

Okay, it is what it is. It works. You can see it here. But I feel like it could be more readable… So I’m giving it another crack while focusing on currying.

const repeatCharacter = (char) => (times) => {
  return new Array(times).fill(char).join("");
}

const repeatSpace = repeatCharacter(" ");
const repeatHash = repeatCharacter("#");

function drawStaircase(n) {
  return new Array(n).fill('')
    .map((row,index) => repeatSpace(n - index + 1) + repeatHash(index + 1))
    .join("\n")
}

See it in action here

I feel like that’s much prettier and easier to follow. Plus, we have this new utility repeatCharacter that we can use elsewhere! (I thought of generalizing to just repeat which would repeat anything n times, but I didn’t want to get too in the clouds for this one silly example.)

In conclusion

I hope I at least got you thinking about how to improve your code. I think this sort of paradigm really does train you to be cleaner, readable, more declarative, and more flexible with your code.

Am I full of crap? Let me know @jschof or in the comments below!

Leave a Reply

Your email address will not be published. Required fields are marked *