1
\$\begingroup\$

I'm trying to practice functional programing using JavaScript. These pure functions just work together to find the difference between two arrays. I know that this might be an impractical example of functional programing, but could you let me know where I can improve or maybe where I've misunderstood an FP technique?

"use strict";

let find = (arr1) => (arr2) => {
  let diff1 = findDiff(arr1)(arr2);
  let diff2 = findDiff(arr2)(arr1);

  return concat(diff1)(diff2);
};

let concat = (arr1) => (arr2) => arr1.concat(arr2);
let findDiff = (arr1) => (arr2) => arr1.filter( (elem) => arr2.indexOf(elem) < 0 );

let sweet = find( [1,2,3,4,5] )( [1,2,3,5,6] );
console.log(sweet);
\$\endgroup\$
2
\$\begingroup\$

I am concerned that you really haven't defined "difference" here and that perhaps your code does not perform the way you expect.

You example is quite simple in that you would expect [4, 6]. But what if you had arrays like:

[1, 1, 2, 2, 3, 3, 4, 4, 5, 5]
[1, 2, 3, 5, 6]

What do you expect to be returned? Currently, your function would return [4, 4, 6], but is that what you expect, or would each instance of a repeated value need to be treated differently (i.e. return would be [1, 2, 3, 4, 4, 5, 6])?

Have you considered flipping your array values into object keys (if type conversion is not a concern) or using Array.sort() on input arrays in combination with fromIndex parameter to Array.indexOf() to minimize array iteration caused by Array.indexOf()? This may not be a concern if you don't expect to be diffing large arrays.

Do you really want to support the find()() syntax for this? I don't really see much value in nesting your function calls in this manner vs. just using:

let find = (arr1, arr2) => {
    // function logic
}

You are not ever returning the intermediate function for possible use elsewhere, so I don't follow the need for this approach.

I agree with the comment from @GregBurghardt around not unneccesarily wrapping native array functions.

I don't like the function being called find. Perhaps something more descriptive to what is actually happening here like arrayDiff(). You are not finding here at all.

To me this whole thing would be clearer/simpler like this:

let arrayDiff = (arr1, arr2) => {
    return arr1.filter( elem => arr2.indexOf(elem) < 0 )
       .concat(
            arr2.filter( elem => arr1.indexOf(elem) < 0 )
       );
};

Note, this obviously does not address some of the questions I asked about uniqueness of array values or optimization of the filter operations.

\$\endgroup\$
  • \$\begingroup\$ Thanks for the insights. Again I'm just diving into fp. I agree with you and @GregBurghardt about wrapping concat(I don't know why I did that). Thanks gents! \$\endgroup\$ – Joseph Palomino Mar 21 '17 at 19:23
1
\$\begingroup\$

Things look fine actually, except the concat function. The problem here is the word "concat" because two things can be commonly concatenated in JavaScript: Strings and Arrays.

The only suggestion I would make is not create a functional wrapper around native functionality.

let find = (arr1) => (arr2) => {
  // ...

  return diff1.concat(diff2);
}

That's a lot easier to read and understand.

\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.