【问题标题】:Functional Programming - Simple For Loop For Incrementing Counter函数式编程 - 用于递增计数器的简单 For 循环
【发布时间】:2016-08-27 01:45:36
【问题描述】:

我们在函数式编程中不使用for loop,而是使用higher order functions,如map、filter、reduce 等。这些都可以用于遍历数组。

但是,我想知道如何进行简单的计数器循环。

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

那么,如何在函数式编程中做到这一点?

【问题讨论】:

    标签: javascript loops for-loop functional-programming counter


    【解决方案1】:

    那么,如何在函数式编程中做到这一点?

    其实没多大用,你还是可以用forEach加一点workaround

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

    5 是您要迭代的次数。

    【讨论】:

    • Array.apply 是一个非常简单的解决方案。不错。
    【解决方案2】:

    使用简单的递归函数

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

    【讨论】:

      【解决方案3】:

      这个怎么样?

      /*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);
      }
      

      然后调用循环如下:

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

      输出: 函数式编程是一种宗教

      函数式编程是一种宗教

      函数式编程是一种宗教

      函数式编程是一种宗教

      函数式编程是一种宗教

      函数式编程是一种宗教

      函数式编程是一种宗教

      函数式编程是一种宗教

      函数式编程是一种宗教

      函数式编程是一种宗教

      请告诉我你对这个答案的看法。

      【讨论】:

      • 函数式编程不会改变输入,因此 scnd 函数将返回 x+1
      【解决方案4】:

      为什么不为数字构建一个高阶函数

      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>'); });

      【讨论】:

      • 我也有同样的想法去做 HOF,所以 +1。不是纯粹的FP,但我是一个实用主义者,不是纯粹主义者。
      【解决方案5】:

      一种函数式方法是编写一个 HOF,它创建一个调用底层函数 n 次的函数:

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

      现在你可以这样调用你的函数:

      function myFunc() { console.log("functional programming is a religion"); }
      
      const tentimes = repeatTimes(myFunc, 10);
      tentimes();
      

      可以通过概括继续重复调用的条件来扩展这种方法。我们将传递一个确定何时停止的函数,而不是一个固定的数字 n。我们将向该函数传递迭代计数:

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

      现在我们称之为

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

      我们可以通过一个创建条件函数的函数来进一步简化这一点,我们称之为lessThan

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

      现在调用可以写成

      const tentimes = repeatWhile(myFunc, lessThan(10));
      tentimes();
      

      【讨论】:

      • 值得注意的是,“纯”函数解决方案将涉及递归,而不是while。然而,在这个时间点上,while 的性能明显优于递归。
      • 我同意不使用 while,因为它是一个控制流,根本不起作用。我会添加我的答案。
      • 这仍然使用“while”
      【解决方案6】:

      重点是让您的大部分代码可测试。对于你的例子,我想最好的方法是创建文本而不打印它。

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

      您可能会说这不是功能性的,这是真的,但它有一个功能性接口。它不会改变它的参数,并且返回的值始终是它的初始参数的直接结果。

      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);
      

      这里的重点是,只要您提供的功能本身不会产生副作用,您就可以对 unFold 的使用进行单元测试。

      【讨论】:

        【解决方案7】:

        不要使用 'while' 或 'for' 来控制非函数式的命令式编程流程。

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

        【讨论】:

        • 这是唯一的纯函数方法,应标记为已接受。所有其他答案都在后台使用 while/if/for。干得好肯
        • 当然,你说它“不是”宗教,但我想我们都知道它是。
        【解决方案8】:

        此函数调用 callbackFn count 次。

        const times = (count, callbackFn) => {
           if (count === 0) {return}
           callbackFn();
           times(count-1, callbackFn);
        }
        
        times(10, () => console.log("Functional Programming is a Religion"));

        这个函数就像一个for循环

        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.");
        });

        这里,上面的函数被用来打印斐波那契数列的前 n 个项

        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);

        【讨论】:

          【解决方案9】:

          当迭代次数很大时,在函数中调用相同的函数需要大量的内存。进一步的cpu时间也增加了。英特尔和ARM等公司 会喜欢这种方法,因为他们正在鼓励软件公司推出 资源匮乏的计划

          无论如何,现在我们处于人工智能时代,需要猛犸象来解决问题,我认为这不是问题。我正在教微处理器和微控制器,可能我的担心是由于这个。 诺尔

          【讨论】:

            【解决方案10】:

            您还可以使用some()every() 来中断或继续您的功能循环。 像这个例子一样,我使用some() 继续,return falsereturn true 中断。

            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)
            })

            【讨论】:

              猜你喜欢
              • 1970-01-01
              • 1970-01-01
              • 2023-01-31
              • 1970-01-01
              • 2013-03-27
              • 1970-01-01
              • 2012-02-27
              • 1970-01-01
              • 1970-01-01
              相关资源
              最近更新 更多