DEV Community

Discussion on: 8 techniques to write cleaner JavaScript code

Collapse
 
regislutter profile image
Régis LUTTER

I don't see the value to use piped functions (even with pipe operator) ? It's less readable and requires more code and characters.

Collapse
 
loucyx profile image
Lou Cyx

Have you actually tried currying? Let's use split as an example to compare different approaches:

// This block are just the values we'll use in our examples, you can ignore them

const spaced1 = "hello world";
const spaced2 = "goodbye world";
const dotted1 = "hello.world";
const dotted2 = "goodbye.world";
const spacedArray = [...Array(10)].fill(spaced1);
const dottedArray = [...Array(10)].fill(dotted2);

/* Without helper functions ***************************************************/

const splitSpaced1 = spaced1.split(" ");
const splitSpaced2 = spaced2.split(" ");
const splitDotted1 = dotted1.split(".");
const splitDotted2 = dotted2.split(".");
const splitSpacedArray = spacedArray.map(spaced => spaced.split(" "));
const splitDottedArray = dottedArray.map(dotted => dotted.split(" "));

/* With helper functions with no options **************************************/

// More code here:
const spaceSplit = string => string.split(" ");
const dotSplit = string => string.split(".");

// But way less code and more readability here:
const splitSpaced1 = spaceSplit(spaced1);
const splitSpaced2 = spaceSplit(spaced2);
const splitDotted1 = dotSplit(dotted1);
const splitDotted2 = dotSplit(dotted2);
const splitSpacedArray = spacedArray.map(spaceSplit);
const splitDottedArray = dottedArray.map(dotSplit);

/* With helper functions with options *****************************************/

// A little bit more code here:
const split = (string, separator) => string.split(separator);

// A little bit more readability and reuse here:
const spaceSplit = string => split(string, " ");
const dotSplit = string => split(split, ".");

// Usage is the same as above, so same benefits

/* With curried functions *****************************************************/

// Same amount of characters as above here:
const split = separator => string => string.split(separator);

// But way less code here, and even more readable:
const spaceSplit = split(" ");
const dotSplit = split(".");

// Usage is almost the same as above, with extra benefits, we'll see that next
Enter fullscreen mode Exit fullscreen mode

You can see you how you only write "more" if you use it once, but the power of currying comes from reuse, and that's where it becomes more readable and where you end up writing more. Keeping the examples above, let's say a new requirement appears in which some strings might come with the _ character, here's how we would solve that with each approach:

const snakeCased = "hello_world";
const snakeCasesArray = [...Array(10)].fill(snakeCased);

/* Without utils **************************************************************/

const splitSnakeCasedArray = snakeCasesArray.map(snakeCased =>
    snakeCased.split("_"),
);

/* With utils without options *************************************************/

// Again like before, we wrote more code (it could be less)
const snakeCaseSplit = string => string.split("_");

// But more readability and less code when using
const splitSnakeCasedArray = snakeCasesArray.map(snakeCaseSplit);

/* With utils with options ****************************************************/

// A little bit of reuse here
const snakeCaseSplit = string => split("_", string);

// Usage is the same as above

/* Finally, with currying *****************************************************/

// Way less code, and still readable
const snakeCaseSplit = split("_");

// And usage can be the same as above, but also if is only once place you could:
const splitSnakeCasedArray = snakeCasesArray.map(split("_"));
Enter fullscreen mode Exit fullscreen mode

I understand that every time we do something thinking in reuse it will require a little bit more characters first, but then it requires less everywhere else. In general readability is improved because we go from stuff like this:

array.map(item => item.split(" "));
Enter fullscreen mode Exit fullscreen mode

To stuff like this:

array.map(split(" "));
Enter fullscreen mode Exit fullscreen mode

Not to mention that map itself can be curried like this:

const map = mapper => array => array.map(mapper);
Enter fullscreen mode Exit fullscreen mode

And then you get even more reuse and readability:

const spaceSplit = split(" ");
const spaceSplitMap = map(spaceSplit);

spaceSplitMap(array);

// And the "inline" version for single case uses:

map(split(" "))(array);
Enter fullscreen mode Exit fullscreen mode

Currying is amazing for code size and reuse, and is very readable if we stay away from "Haskell like" practices like having single character arguments. Hope this helps see the value of currying more clearly. I was requested a few times to do a full post on the subject and I will do it soon, so I'll try to remember to let you know about it if you still don't see the value in this.

Cheers!