Syntax 如何使用let in F#创建新的作用域?
我试图在F#中初始化一个XmlDocument,而不污染全局名称空间——我唯一的功能背景来自LISP,在LISP中可以使用“let”创建一个新的作用域。我想到了这个:Syntax 如何使用let in F#创建新的作用域?,syntax,f#,Syntax,F#,我试图在F#中初始化一个XmlDocument,而不污染全局名称空间——我唯一的功能背景来自LISP,在LISP中可以使用“let”创建一个新的作用域。我想到了这个: let doc = let reader = new XmlTextReader("url") let doc = new XmlDocument() doc.Load(reader) doc 当我的第一个解决方案不起作用时,我感到相当惊讶: let doc = new XmlDocument(
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!
做我想做的事情的首选方式是什么 你的第一个例子似乎是Don Syme和其他F#爱好者采用的风格。混合
#灯光和ML风格让。。在
中似乎不是个好主意
你可以从中阅读一些样品来感受当代的F#风格
还有Don Syme写的。似乎当你使用“let..in”时,你可以覆盖默认的“#light”设置,即空格是重要的,所以我想这就是在这种情况下发生的情况,以及为什么在第二种情况下你没有得到任何警告/错误(您添加了'in',因此编译器认为您需要显式指定范围)。这似乎有点奇怪,因此可能是一个bug。我相信F#团队的Brian很快会回答这个疑问:-)
无论如何,我认为编译器将您的第二个示例视为(使用更容易编译的示例):
本例先打印“10”,然后打印“1”。当然,这似乎不是很实用,但是当使用use
关键字时它很有用,该关键字的行为类似于let
,但适用于IDisposable
对象,并确保对象在离开作用域时被释放(这与C#中的using
一样):
编辑:
我完全忘了提到重要的一点——编写代码的第一种方式对我来说似乎更自然(它充分利用了F提供的“简单”语法的优点),所以我更喜欢它:-) 问题的一部分可能是“let…in…”是一个表达式,而不是一个语句,因此在顶层使用此构造实际上没有意义。例如,这意味着什么:
let x = 1 in
x - 5
在高层?似乎编译器应该在顶层将“let…in…”的任何使用标记为错误
另一个问题是xmldocumentapi根本不是以函数式风格编写的,这使得从F#开始使用有点尴尬。我想说,您的第一次尝试与您将要得到的一样好,但如果API允许以下内容,那就太好了:
let doc =
let reader = new XmlTextReader("url")
reader.ReadAsDocument()
或者,如果有一个XmlDocument的构造函数使用了XmlReader,但是由于API是无可非议的必需的,那么您就必须去做。事实上,使用let。。在with中,不需要使用#light选项,尽管从规范来看,它仍然作为可选语法有效。读者仍然在范围内这一事实对我来说确实很奇怪。可能是虫子吧?在我看来,它看起来像虫子。但他在这个例子中混合了很多东西:#光,这个‘’运算符、缩进和“in”。F#的语法远不是优雅的,也不是直观的——合并ML和.NET留下了太多的包袱……哇,很好的一个。如果布瑞恩不回答这个问题,你应该考虑把它发送到fsbgs@微软.com。我打开了bug 4693。避免光照代码中的“让……进来”。
let a = 1
(let a = a + 10
printfn "%d" a)
printfn "%d" a
let some = new Some()
(use file = new StreamReader(...)
let txt = file.ReadToEnd()
printfn "%s" txt)
doSomething() // continue, 'file' is now closed!
let x = 1 in
x - 5
let doc =
let reader = new XmlTextReader("url")
reader.ReadAsDocument()