F# 记录类型递归成员函数和;rec";关键词

F# 记录类型递归成员函数和;rec";关键词,f#,recursion,record,F#,Recursion,Record,我一直认为,在F#中,我们需要对每个递归函数使用rec关键字,例如: let rec factorial = function | 0 -> 1 | k when k > 0 -> k * (factorial (k - 1)) | failwith "oops!" 今天我在玩F#,我想出了一个类似以下的代码: let MyRecordType = { Something : float; SomethingElse : int } wi

我一直认为,在F#中,我们需要对每个递归函数使用
rec
关键字,例如:

let rec factorial = function
| 0 -> 1
| k when k > 0 ->  k * (factorial (k - 1))
| failwith "oops!"
今天我在玩F#,我想出了一个类似以下的代码:

let MyRecordType =
    { Something     : float;
      SomethingElse : int }
    with
        static member factorial = function
            | 0 -> 1
            | k when k > 0 ->  k * (MyRecordType.factorial (k - 1))
            | failwith "oops!"
如您所见,我刚刚定义了一个递归函数,但我犯了一个起初似乎是错误的错误:我忘了通过
rec
关键字将函数声明为递归函数

但令我惊讶的是,它编译了!还有更多:如果您添加
rec
关键字,那么这是一个语法错误

type MyRecordType =
    { (* ... *) }
    with
        // syntax error:
        static member rec factorial = function
        (* ... *)
我在谷歌上搜索了一下,想找个解释,但一无所获。在MSDN文档中,我找不到任何外部提到的
rec
关键字,并且截至2010-01-03,它没有提到我正在询问的案例

非静态成员也会发生同样的情况


因此,为什么在记录类型的成员函数上使用
rec
关键字是一个语法错误?

“let rec”不是关于定义递归函数,而是在一个环境中定义一个绑定,其中包括当前 要绑定的变量。您也可以使用“let rec”来定义无限列表。通常,您不希望包含绑定 在环境中,因为您可能希望使用相同的名称访问较早的变量

当您定义静态成员函数factorial时,您不是在寻找变量“factorial”的绑定,而是在寻找类型 “MyRecordType”(作为类型定义在环境中),如果它碰巧有一个名为“factorial”的静态成员函数,
它有。

所有“成员”函数都隐式地“rec”在它们定义的类型中。

有趣。谢谢只是一个问题:我们希望以相同的名称访问早期值的频率是多少(对我来说,这似乎是非常罕见的)?为什么会有人需要呢?是的,我认为我的答案中的“经常”是误导性的。我应该说“有时”。如果需要访问新变量,可以将其重命名为与先前的变量名不冲突的名称。有时重用变量名会更方便。我手边没有任何好的例子,但例如“let tot1=a+b in let tot2=tot1/10 in let tot3=tot2+8 in let tot4=tot3%15 in tot4”如果是“let tot=a+b in let tot=tot/10 in let tot=tot+8 in let tot=tot%15 in tot”,通常会更容易阅读(并进行修改!)。谢谢。如果能在MSDN上的某个地方为RTM记录这一点,那就太好了!正是我想要的