Joa*_*nge 15 recursion f# function
我不确定这是否是一个愚蠢的问题,但我正在阅读VS 2010附带的教程,并且有一个这样的函数:
let rec factorial n = if n=0 then 1 else n * factorial (n-1)
Run Code Online (Sandbox Code Playgroud)
这个递归函数用rec关键字标记的原因是什么?
这样编译器可以确保它是递归的,所以可以进行某些优化吗?
如果排除它会怎么样?
Bri*_*ian 28
这可能是有益的:
let Main() =
let f(x) =
printfn "original f: %d" x
let f(x) =
//let rec f(x) =
printfn "entered new f: %d" x
if x > 0 then
f(x-1)
else
printfn "done"
f(3)
Main()
Run Code Online (Sandbox Code Playgroud)
那打印
entered new f: 3
original f: 2
Run Code Online (Sandbox Code Playgroud)
现在,如果我们注释掉let并取消注释let rec,则打印出来
entered new f: 3
entered new f: 2
entered new f: 1
entered new f: 0
done
Run Code Online (Sandbox Code Playgroud)
所以从这个角度来看,它只是名称绑定; let rec将标识符立即放入作用域(在此示例中,遮蔽前一个f),而let仅在定义其正文后将标识符放在作用域中.
规则的动机源于与类型推断的交互.
Rus*_*Cam 11
据Chris Smith说(在F#团队工作) -
通知类型推断系统允许该函数用作类型推断过程的一部分.rec允许您在类型推断系统确定函数类型之前调用该函数
根据MSDN,它只是一种合成必需品:
递归函数,调用自身的函数,在F#语言中明确标识.这使得在函数范围内定义的标识符可用.
http://msdn.microsoft.com/en-us/library/dd233232.aspx
这个递归函数用rec关键字标记的原因是什么?
告诉编译器函数体内函数名的任何使用都是递归地引用它而不是先前定义的同名值.
这样编译器可以确保它是递归的,所以可以进行某些优化吗?
没有.
如果排除它会怎么样?
您失去了定义的函数在其函数体中引用自身的能力,并且能够引用先前定义的同名值.
这是必要的,以便函数可以递归.非rec函数只知道绑定在它定义的地方,而不是之后(所以它不知道自己).
| 归档时间: |
|
| 查看次数: |
1835 次 |
| 最近记录: |