12

以下の最初の定義では、f# 3.0 で警告レベルを 5 に設定してコンパイルすると、タイトルに警告が表示されます。2 番目の定義は問題なくコンパイルされます。誰かが私が誤って変更する可能性があることをコンパイラが心配していること、または let 句で式を分割するとそれを回避するのにどのように役立つかを説明してもらえないだろうかと思いました。どうもありがとう。

let ticks_with_warning () : int64 =
   System.DateTime.Now.Ticks 

let ticks_clean () : int64 =
   let t = System.DateTime.Now
   t.Ticks 
4

1 に答える 1

12

特定のケースでコンパイラがこの警告を発する理由を実際に説明することはできません。コンパイラはおそらく過度に慎重であるため、無視しても問題ないという@ildjarnに同意します。

ただし、警告が実際に何かが期待どおりに進まない可能性があるという有用なヒントを与える可能性がある例を示すことができます。このようなミュータブルがある場合struct

[<Struct>]
type Test =
  val mutable ticks : int64
  member x.Inc() = x.ticks <- x.ticks + 1L
  new (init) = { ticks = init }

ここで、Incメソッドは構造体を変更します(また、変更可能なフィールドにアクセスすることもできますticks)。Test値を作成してそれを変更する関数を書いてみることができます。

let foo () =
  let t = Test(1L)
  t.Inc()  // Warning: The value has been copied to ensure the original is not mutated
  t

tローカル値をとしてマークしなかったmutableため、コンパイラは、を呼び出すときに値が変更されていないことを確認しようとしますInc。値を変更するかどうかはわからないIncため、安全なのはコピーを作成することだけです-したがってfoo、値を返しますTest(1L)

tとしてマークを付けるとmutable、コンパイラは呼び出しの結果としてそれを変更することを心配する必要がないため、警告を表示しません(そして関数は戻りますTest(2L)):

let foo () =
  let mutable t = Test(1L)
  t.Inc()
  t

ただし、例の警告の原因はよくわかりません。おそらく、コンパイラーは(いくつかの中間表現の結果として)Ticks操作が左側の値(System.DateTime.Nowおよびtそれぞれ)を変更する可能性があると考えており、それを防ぎたいと考えています。

奇妙なことに、F#で独自の構造体を作成すると、変数を(私が期待するものです)としてDateTimeマークしない限り、どちらの場合も警告が表示されますが、標準での動作は異なります。したがって、おそらくコンパイラは、私が欠落している標準型について何かを知っています...tmutableDateTime

于 2012-12-06T22:55:24.270 に答える