ES6 Trampoline函数

ES6 Trampoline函数

在本文中,我们将尽可能详细地了解ES6中与Trampoline函数相关的每个方面。让我们首先了解在使用递归时出了什么问题,然后了解尾递归的概念,然后我们将了解为何需要在ES6中引入另一个名为Trampoline函数的函数。

递归出了什么问题?

递归是一种现象或过程,我们通过同一个函数进行多个不同函数调用来计算任何结果值,这些调用由/在栈数据结构中进行管理。递归实际上使代码更简单,并且对于较大的值,实际上将结果逐一解决(也就是逐个值)。

示例:

让我们看下面的代码片段,以便更快而且不高效地理解递归。

Javascript

let sumCalculation = (num) => { 
  let sum = 0; 
  return num === 0 ? sum : num + sum + sumCalculation(num - 1); 
}; 
  
console.log(sumCalculation(5)); 
console.log(sumCalculation(13));

输出:

15
91

示例: 以下的代码片段展示了上面递归代码的执行。

sumCalculation(5){
    sum = 5
        sumCalculation(4) {
            sum = 5 + 4 
                sumCalculation(3){
                    sum = 5 + 4 + 3
                        sumCalculation(2){
                            sum = 5 + 4 + 3 + 2
                                sumCalculation(1){
                                    sum = sum = 5 + 4 + 3 + 2 + 1
                                        sumCalculation(0){
                                            // Returns sum = 15
                                            // Exist all function calls
                                        }
                                }
                        }
                }
        }
}

如上所示,会进行很多函数调用,因此对于较大的输入大小,控制台输出可能会显示“Range Error: Maximum call stack size exceeded”。

为了消除这个错误,一种重要的概念被引入,即尾递归(在下面解释)。

尾递归: 这是一种与常规递归不同的现象或过程,其中我们将下一个递归步骤中的变化结果作为操作数传入,而不是传递一个函数。这个特殊的过程有助于防止堆栈溢出,但也存在一些相关的问题,稍后将在本节的后面部分进行描述。

示例: 以下代码片段将更清楚地说明问题。

Javascript

let sumCalculation = (num) => { 
  let sumRecursiveCalculation = (result, num) => { 
    return num === 1 ? result : sumRecursiveCalculation(result + num, num - 1); 
  }; 
  return sumRecursiveCalculation(1, num); 
}; 
  
console.log(sumCalculation(5)); 
console.log(sumCalculation(15));

输出:

15
120

现在存在的问题是JavaScript不认识尾递归,因此即使对于较大的输入,错误仍然是“范围错误:最大调用堆栈大小存在”,因为JavaScript将尾递归视为普通递归,因此在调用堆栈下执行。

平台函数:

这个平台函数实际上是用于实现尾递归的辅助函数。在此过程中,我们将所有嵌套的函数调用转换为顺序的函数调用数量,从而帮助我们避免堆栈溢出的情况。

平台函数基本上将递归函数包装在循环中,并且进一步调用该递归函数,直到不再存在递归调用为止。

尽管平台函数是JavaScript中展示函数式编程的最佳例子。此函数将为我们提供更大值的结果,而以前提到的技术(无论是普通递归还是尾递归)都无法实现。

示例: 下面的代码片段将更清楚地说明这个平台函数的工作原理:

JavaScript

// Trampoline function Implementation 
const trampoline_function = (func) => (...rest_arguments) => { 
  let result = func(...rest_arguments); 
  while (typeof result === 'function') { 
    result = result(); 
  } 
  return result; 
}; 
  
// Sum Calculation Program Implementation 
const sumCalculation = (num, sum = 0) => { 
  return num === 0 ? sum : () => sumCalculation(num - 1, sum + num); 
}; 
  
// Wrapping function in Trampoline function 
// which is implemented above 
const sumCalculate = trampoline_function(sumCalculation); 
console.log(sumCalculate(5)); 
console.log(sumCalculate(1000000));

输出:

15
500000500000

Python教程

Java教程

Web教程

数据库教程

图形图像教程

大数据教程

开发工具教程

计算机教程