[英]How to create a new scope using let in F#?
我正在尝试在 F# 中初始化一个 XmlDocument,而不会污染全局命名空间 - 我唯一的功能背景来自 LISP,其中可以使用“let”创建一个新的 scope。 我想出了这个:
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”,因此编译器认为您要明确指定 scope)。 这似乎有点奇怪,所以它可能是一个错误。 我确信来自 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”。 当然,这似乎不太实用,但是在使用行为类似于let
的use
关键字时很有用,但适用于IDisposable
对象并确保 object 在离开 scope 时被释放(这就像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 语法的好处),所以我更喜欢它:-) .
部分问题可能是“let... in...”是一个表达式,而不是一个语句,所以在顶层使用这个结构并没有真正的意义。 例如,这意味着什么:
let x = 1 in
x - 5
在顶层? 似乎编译器应该在顶层将“let... in ...”的任何使用标记为错误。
另一个问题是 XmlDocument API 不是以函数式样式(根本)编写的,这使得从 F# 使用它有点尴尬。 我想说您的第一次尝试与您将要获得的一样好,但如果 API 允许更多类似的东西肯定会很好:
let doc =
let reader = new XmlTextReader("url")
reader.ReadAsDocument()
或者,如果有一个 XmlDocument 的构造函数采用 XmlReader,但由于 API 毫无歉意地势在必行,你将不得不凑合。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.