首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >F#中的递归对象?

F#中的递归对象?
EN

Stack Overflow用户
提问于 2011-12-26 14:30:31
回答 1查看 1.3K关注 0票数 8

这段F#代码片段

代码语言:javascript
复制
    let rec reformat = new EventHandler(fun _ _ ->
        b.TextChanged.RemoveHandler reformat
        b |> ScrollParser.rewrite_contents_of_rtb
        b.TextChanged.AddHandler reformat
        )
    b.TextChanged.AddHandler reformat

下列警告的结果:

traynote.fs(62,41):警告FS0040:将通过使用延迟引用在运行时检查对所定义对象的此引用和其他递归引用的初始化是否合理。这是因为您定义的是一个或多个递归对象,而不是递归函数。这个警告可以通过使用‘40’或‘--现在’40‘来抑制。

是否有方法可以重写代码以避免此警告?或者在F#中没有更好的方法来拥有递归对象?

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2011-12-26 16:39:16

您的代码是构造递归对象的非常好的方法。编译器会发出警告,因为它不能保证在初始化引用之前不会访问它(这会导致运行时错误)。但是,如果您知道EventHandler在构造过程中没有调用提供的lambda函数(它不调用),那么您可以安全地忽略警告。

要给出警告实际显示问题的示例,您可以尝试以下代码:

代码语言:javascript
复制
type Evil(f) =
  let n = f() 
  member x.N = n + 1

let rec e = Evil(fun () -> 
  printfn "%d" (e:Evil).N; 1)

Evil类在构造函数中接受一个函数,并在构造过程中调用它。因此,lambda函数中的递归引用在将其设置为值之前尝试访问e (您将得到一个运行时错误)。但是,特别是在使用事件处理程序时,这不是一个问题(当您正确地使用递归对象时,您会得到警告)。

如果您想消除警告,可以使用显式ref值和null重写代码,但是运行时错误的危险是相同的,只是没有警告,代码更丑:

代码语言:javascript
复制
let foo (evt:IEvent<_, _>) = 
  let eh = ref null
  eh := new EventHandler(fun _ _ -> 
    evt.RemoveHandler(!eh) )
  evt.AddHandler(!eh)
票数 16
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/8636630

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档