当使用f#3.0编译并且警告级别设置为5时,下面的第一个定义在标题中产生警告.第二个定义干净地编译.我想知道是否有人可以解释编译器担心我可能会意外改变的内容,或者如何使用let子句分割表达式有助于避免这种情况.非常感谢.
let ticks_with_warning () : int64 =
System.DateTime.Now.Ticks
let ticks_clean () : int64 =
let t = System.DateTime.Now
t.Ticks
Run Code Online (Sandbox Code Playgroud)
Tom*_*cek 11
我无法解释为什么编译器会在您的特定情况下发出此警告 - 我同意@ildjarn您可以放心地忽略它,因为编译器可能只是过于谨慎.
但是,我可以给你一个例子,警告可能会给你一个有用的提示,说明某些事情可能没有你想象的那样.如果我们有这样的可变struct:
[<Struct>]
type Test =
val mutable ticks : int64
member x.Inc() = x.ticks <- x.ticks + 1L
new (init) = { ticks = init }
Run Code Online (Sandbox Code Playgroud)
现在,该Inc方法改变了struct(你也可以访问mutable字段ticks).我们可以尝试编写一个创建Test值并使其变异的函数:
let foo () =
let t = Test(1L)
t.Inc() // Warning: The value has been copied to ensure the original is not mutated
t
Run Code Online (Sandbox Code Playgroud)
我们没有将本地值标记t为mutable,因此编译器会在我们调用时尝试确保该值不会发生变化Inc.它不知道是否Inc改变了值,所以唯一安全的是创建一个副本 - 从而foo返回值Test(1L).
如果我们标记t为mutable,那么编译器不必担心因调用而改变它,因此它不会发出警告(并且函数返回Test(2L)):
let foo () =
let mutable t = Test(1L)
t.Inc()
t
Run Code Online (Sandbox Code Playgroud)
我不确定在你的例子中导致警告的是什么.也许编译器认为(作为一些中间表示的结果)Ticks操作可以改变左侧值(System.DateTime.Now和t分别)并且它想要阻止它.
奇怪的是,如果你DateTime在F#中编写自己的结构,除非你将变量标记t为mutable(这是我期望的),否则在两种情况下都会收到警告,但标准的行为DateTime是不同的.所以也许编译器知道我遗漏的标准类型...