函数递归
局部函数变量的特性自成体系,作为调用函数自身
递归函数不依靠任何外部资源,自成体系的迭代到基准值
return:返回特定的退出状态码,在函数结束时
#! /bin/bash
# using recursion
# 计算阶乘,formula:x!=x*(x-1)!, 使用递归函数得到(x-1)!
function factorial {
# 递归边界,根据1的阶乘是1
if [ $1 -eq 1 ]; then
echo 1
else
local temp=$[ $1 -1 ]
# 接收函数的输出,并将返回值传递给result
local result=$(factorial $temp)
echo $[ $result * $1 ]
fi
}
read -p "Enter value: " value
# result与自成体系的递归函数不同, local局部变量
result=$(factorial $value)
echo "The factorial of $value is : $result"
///: C:计算阶乘
// 递归公式推导: m*(m-1)!
#include
long fact(int num) {
long result,args;
if(num==1) {
// 设置边界条件,底层回溯值
return 1;
} else {
args = num - 1;
result = fact(args);
return num * result;
}
}
int main(void) {
int num, result;
printf("请输入一个要计算的阶乘数: ");
scanf("%d",&num);
result = fact(num);
printf("这个数的阶乘是: %d", result);
}
// 通过逻辑与的短路特性作为简单if-else
// 计算 1+2+...+9+10
#include
using namespace std;
int add(int c);
int main()
{
add(10);
return 0;
}
int add(int c) {
int a = 0;
c && (a=add(c-1)); //函数自递归 底层调用return的另一种方式:终止函数
cout << c+a<< endl;
return a + c;
}
理解优化
当到达递归边界后,函数return最底层被调用并开始回溯
递归函数的return(回溯)顺序和调用顺序刚好相反!
那是因为上一层执行递归之后的代码会调用下一层返回的值
亦或者说:最底层的实现(return1)作为最外层的调用(return4),如此循环往复
例如,计算 factorial 4 的过程如下:
factorial 4 调用 factorial 3,返回 3 * factorial 3。
factorial 3 调用 factorial 2,返回 2 * factorial 2。
factorial 2 调用 factorial 1,返回 1 * factorial 1。
factorial 1 返回 1。
逐层返回时:
factorial 2 返回 2 * 1 = 2。
factorial 3 返回 3 * 2 = 6。
factorial 4 返回 4 * 6 = 24。
当递归停止后,函数内部的result返回的是之后的阶乘,因为每一层递归都会将当前的 result 乘以当前的 $1,直到最外层调用。
底层理解:函数调用时,从上层到下层的顺序依次压入保存到栈内存,先进后出,最后调用的会被优先执行并回溯
函数闭包
var count=(function () {
var count=0; //延长变量生存期
return function() { //外部函数一直实现内部函数
return count+=1; //内部函数一直引用外部函数
}
})();
function func() {
var result=count();
document.getElementById("demo").innerHTML=result;}
JavaScript
function Myfunction(a,b) {
return a*b;
}
document.getElementById("demo").innerHTML="4*5的结果为:" +Myfunction(4,5);
// 需要定义形参,不存在#!判断最后一条语句
// 即不存return不会将函数最后一条语句作为返回值
Bash
#!/bin/bash
function Myfunction {
local param="$1"
echo $param
}
result=$(Myfunction "helloworld")
echo $result
## 无需定义形参 存在#!判断最后一条语句(退出码)
## 即不存return会将最后一条语句作为返回值
## 传递过程无需括号(同此可省略括号)