15

We dont use for loop in functional programming, instead, we use higher order functions like map, filter, reduce etc. These are fine for iterating through an array.

However, I wonder how do I do a simple counter loop.

let i = 0;
for( i; i < 10; i++) {
  console.log( "functional programming is a religion")
};

So, how would one do this in functional programming?

Kayote
  • 14,579
  • 25
  • 85
  • 144

10 Answers10

40

Do not use 'while' or 'for' that is to control flows of Imperative Programming not Functional.

Array(10).fill("functional programming is not a religion")
.map((msg) => {
  console.log(msg);
  return msg;
});
15

A functional approach would be to write a HOF which creates a function which calls an underlying function n times:

function repeatTimes(fn, n) {
  return function() {
    while (n--) fn(...arguments);
  };
}

Now you would call your function as follows:

function myFunc() { console.log("functional programming is a religion"); }

const tentimes = repeatTimes(myFunc, 10);
tentimes();

This approach can be extended by generalizing the condition for continuing the repeated calls. Instead of a fixed number n, we will pass a function which will determine when to stop. We will pass that function the iteration count:

function repeatWhile(fn, cond) {
  return function() {
    var count = 0;
    while (cond(count++)) fn(...arguments);
  };
}

Now we call this as

const tentimes = repeatWhile(myFunc, i => i < 10);
tentimes();

We could further streamline this via a function which creates the condition function, which we would call lessThan:

function lessThan(n) { return i => i < n; }

Now the invocation can be written as

const tentimes = repeatWhile(myFunc, lessThan(10));
tentimes();
  • 8
    It's worth noting that a "pure" functional solution would involve recursion, and not `while`. However, at this point in time, `while` is significantly more performant than recursion. – Madara's Ghost May 03 '16 at 09:04
  • I agree not to use while, because it's a control flow and not functional at all. I will add my answer. –  Jul 08 '18 at 14:31
  • this still using "while" – Leo Lanese Aug 06 '18 at 10:53
4

So, how would one do this in functional programming?

It is not doing much actually, you can still use forEach with a little workaround

Array.apply(null, Array(5)).forEach(function(){
 console.log( "funtional programming is a religion")
});

5 is the number of times you want to iterate.

Community
  • 1
  • 1
gurvinder372
  • 66,980
  • 10
  • 72
  • 94
2

The whole point would be to make most of your code testable. For you example I guess the best would be to create the text without printing it.

function unFold(fnStopPredicate, fnTerm, fnGenerate, aSeed) {
    var arr = [];
    while( ! fnStopPredicate(aSeed) ){
        arr.push(fnTerm(aSeed));
        aSeed = fnGenerate(aSeed);
    }
    return arr;
}

You might say this is not functional and that is true, BUT it has a functional interface. It does not mutate it's arguments and the value returned is always a direct result of it's initial arguments.

var strValues = unFold(x => x > 10,
                       x => "functional programming is a religion",
                       x => x+1,
                       0).join("\n");

// Real side effect goes here
console.log(strValues);

The main point here is that you may unit test the use of unFold as long as the function you provide does not do side effects themselves.

Sylwester
  • 47,942
  • 4
  • 47
  • 79
1

Why not build a Higher Order Function for Numbers.

Number.prototype.repeat = function (fn) {
    var i,
    n = Math.abs(Math.floor(this)) || 0;
    for (i = 0; i < n; i++) fn(i, this);
};

(10).repeat(function (i, n) { document.write(i + ' of ' + n + ': your claim<br>'); });
(NaN).repeat(function (i, n) { document.write(i + ' of ' + n + ': your claim<br>'); });
Nina Scholz
  • 376,160
  • 25
  • 347
  • 392
1

You could also use some() or every() to break or continue your functional loop. Like this example, I use some() to continue with return false and return true to break.

Array(10).fill("message").some((msg,index) => {
            
    //like continue loop
    if(index === 5) return false 
    //like break loop
    if(index === 9) return true

    console.log(msg, index)
})
JoeHogans
  • 11
  • 1
0

How about this?

/*forLoop takes 4 parameters
 1: val: starting value.
 2: condition: This is an anonymous function. It is passed the current value.
 3: incr: This is also an anonymous function. It is passed the current value.
 4: loopingCode: Code to execute at each iteration. It is passed the current value.
*/

var forLoop = function(val, condition, incr, loopingCode){
  var loop = function(val, condition, incr){
    if(condition(val)){
        loopingCode(val);
        loop(incr(val), condition, incr);
    }
  };
  loop(val, condition, incr);
}

Then call the loop as follows:

    forLoop(0, 
      function(x){return x<10},
      function(x){return ++x;}, 
      function(x){console.log("functional programming is a religion")}
      );

Output: functional programming is a religion

functional programming is a religion

functional programming is a religion

functional programming is a religion

functional programming is a religion

functional programming is a religion

functional programming is a religion

functional programming is a religion

functional programming is a religion

functional programming is a religion

Do let me know What you think about this answer.

Akshay Shinde
  • 141
  • 3
  • 16
0

This function calls callbackFn count times.

const times = (count, callbackFn) => {
   if (count === 0) {return}
   callbackFn();
   times(count-1, callbackFn);
}

times(10, () => console.log("Functional Programming is a Religion"));

This function works like a for-loop

const forLoop = (initialValues, conditionFn, newValsFn, bodyFn) => {
   if (!conditionFn(initialValues)) {return}
   bodyFn(initialValues);
   forLoop(newValsFn(initialValues), conditionFn, newValsFn, bodyFn);
}

forLoop({i: 0}, ({i}) => i < 10, ({i}) => ({i: i+1}), ({i}) => {
   console.log(i, "Functional Programming is a Religion.");
});

Here, the above function is being used to print the first n terms of the Fibonacci Series

const forLoop = (initialValues, conditionFn, newValsFn, bodyFn) => {
   if (!conditionFn(initialValues)) {return}
   bodyFn(initialValues);
   forLoop(newValsFn(initialValues), conditionFn, newValsFn, bodyFn);
}

const fibPrint = (n) => {
   let n1 = 0, n2 = 1, nextTerm;
    
   forLoop({i: 1}, ({i}) => i <= n, ({i}) => ({i: i+1}), () => {
      console.log(n1);
      nextTerm = n1 + n2;
      n1 = n2;
      n2 = nextTerm;
   });
}

fibPrint(10);
-1

calling same function with in the function requires lot of memeory when the iterating number is very big. further cpu time is also increased. companies like intel and arm will love this approach since they are instigating software companies to bring out resource hungry programs

anyway now we ae in the age of AI which requires mamoths to solve problems, i think this will not an issue. I am teaching microprocessors and microcontrollers, Probably my apprehension is is due to this. noor

-2

Use a simple recursive function

function counter(value) {
    var i = value;
    if(i<10){
        console.log( "functional programming is a religion");
    }else{
        return;
    }
        counter(++i);    
}
  counter(0);
sarath
  • 343
  • 8
  • 31