我正在尝试在F#中初始化XmlDocument,而又不污染全局 namespace -我唯一的功能背景来自LISP,在这里LISP可以使用“let”创建新作用域。我想出了这个:

let doc =
    let reader = new XmlTextReader("url")
    let doc = new XmlDocument()
    doc.Load(reader)
    doc

当我的第一个解决方案不起作用时,我感到非常惊讶:
let doc = new XmlDocument() in
    let reader = new XmlTextReader("url");
    doc.Load(reader)

print_any reader.ToString // Still in scope!

我想要做什么的首选方式是什么?

最佳答案

看来,当您使用“let .. in”时,您可以覆盖默认的“#light”设置,即空格很重要,因此我想在这种情况下会发生这种情况,以及为什么您在其中没有收到任何警告/错误第二种情况(您添加了“in”,因此编译器认为您想显式指定范围)。似乎有点怪异,所以可能是一个错误。我敢肯定F#小组的Brian会尽快回答这个问题的:-)。

无论如何,我认为编译器将您的第二个示例视为(使用易于编译的示例):

open System

let ar = new ResizeArray<_>() in
let rnd = new Random();
ar.Add(rnd.Next())

printfn "%A" (rnd.Next())

如果添加括号并编写如下内容,则可以强制其按需要对其进行处理:
let ar = new ResizeArray<_>() in
    (let rnd = new Random()
     ar.Add(rnd.Next()))

printfn "%A" (rnd.Next())

通常,可以在F#程序的任何位置使用括号来指定范围。例如,您可以编写:
let a = 1
(let a = a + 10
 printfn "%d" a)
printfn "%d" a

本示例先打印“10”,然后打印“1”。当然,这似乎不太实用,但是在使用行为类似于uselet关键字但对IDisposable对象有效并确保对象离开作用域时将其处置(这就像using时)很有用。在C#中):
let some = new Some()
(use file = new StreamReader(...)
 let txt = file.ReadToEnd()
 printfn "%s" txt)
doSomething() // continue, 'file' is now closed!

编辑:
我完全忘记了重要的一点-第一种编写代码的方式对我来说似乎更自然(并且完全利用了F#提供的“简单” #light语法的优点),所以我更喜欢它:-)。

09-10 11:52
查看更多