trekhleb / javascript-algorithms

📝 Algorithms and data structures implemented in JavaScript with explanations and links to further readings
MIT License
187.71k stars 30.17k forks source link

My concern about no classification by Procedural/Imperative and Functional programming Paradigm #119

Open ken-okabe opened 6 years ago

ken-okabe commented 6 years ago

Hi, this is a great project. Thanks. I have a concern that I would like to share.

For instance, looking at /algorithms/math/factorial which is one of the most basic math topic: https://github.com/trekhleb/javascript-algorithms/tree/master/src/algorithms/math/factorial

I found 2 implementations:

factorial.js

export default function factorial(number) {
  let result = 1;

  for (let i = 2; i <= number; i += 1) {
    result *= i;
  }

  return result;
}

factorialRecursive.js

export default function factorialRecursive(number) {
  return number > 1 ? number * factorialRecursive(number - 1) : 1;
}

factorial.js is a code of Procedural/Imperative programming style, and uses mutable variables.

factorialRecursive.js is recursive, and can be said functional programming style, immutable. Alghouth this is a typical implementation which I can see everywhere, in terms of "Big O notations". this is rather anti-pattern.

A better or I would say, a proper way is,

factorialFunctional.js

//[...Array(5).keys()]
//-> [ 0, 1, 2, 3 ,4 ]

const natural = n => {
    const arr0 = [...Array(n + 1).keys()];
    const [first, ...arr] = arr0;
    return arr;
};

console.log(
    natural(5) //[ 1, 2, 3, 4, 5 ]
);

function factorialFunctional(number) {
    const list = number < 1
        ? [1]
        : natural(number)
    const multiply = (a, b) => a * b;
    return list.reduce(multiply);
}

console.log(
    factorialFunctional(5)//120
);

This is as efficient as the factorial.js in terms of "Big O notations", and immutable.

I think when algorithms are presented, it's significantly important to clarify what kind of programming paradigm the algorithms are based on.

Currently, it seems the contributions are updated randomly without formal classification for them, and I think it's a good idea to show a guideline in the README that to clarify which paradigm every algorithm belongs to. In this manner, a contributors notice "oh, here, there is no Functional or Imperative pattern yet, so I will add.."

Thanks.

trekhleb commented 6 years ago

Thank you for your suggestion @kenokabe.

Interesting implementation of factorial!

What programming paradigms do you mean? I mean how do you suggest to split algorithms in main README? Is it something from https://en.wikipedia.org/wiki/Programming_paradigm like imperative and declarative? Or more detailed like object-oriented, procedural and functional?

ken-okabe commented 6 years ago

Thanks for your response and the great project again @trekhleb . As you suggest, the classification is another issue to be considered. It's often not easy.

An idea to classify things, especially these days, is not to "split" but to "tag" the algorithms. One algorithm can be tagged as "#imperative #procedual #object-oriented", another can be "#functional #declarative #lazy-evaluation". Tagging is a good method to express classifications that cross over.

Again, I really think it's not great especially for learners that we put algorithms for a certain target in the same box of mixed programming paradigms without any classifications.

trekhleb commented 6 years ago

@kenokabe I like the idea with tagging! It may be one of the next enhancements to do here in this repo. Thank you for suggestion!

georgebullock commented 5 years ago

Is this going to happen? For a learning project, I think it would be valuable.