@李的回答是正確的每個可能的解決方法,但它沒有描述你的代碼會發生什麼。
在表達printf "foo"
,所述"foo"
不被格式化的字符串。相反,它本身是輸入格式器。更具體地說,它是一個字符串文字,用於推斷TextWriterFormat<'T>
的實際類型。
printf
的簽名是:
printf : TextWriterFormat<'T> -> 'T
由於printfn ("DANNY")
不包含任何格式說明中,F#編譯器推斷一個TextWriterFormat<unit>
,並且整個表達式變爲printfn ("DANNY")()
。
有了變量,這是不可能的靜態預測符將會有什麼樣的格式。試想,如果ToLongTimeString()
方法能夠返回"%s"
或"%d %d %d"
字符串,這將是返回函數的原型?
當推斷正確的類型,字符串字面工作正常,但是變量或let
結合位不起作用:
let foo1 = "foo"
let bar = printf foo // does not compile
[<Literal>] let foo2 = "foo";; // see update below
let bar = printf foo2 // compiles fine
在任何情況下,它看起來更安全,始終使用指定格式有:
printf "%s" "DANNY"
printf "%s" (DateTime.Now.ToLongTimeString())
更新:不要忘了後[<Literal>]
價值型雙冒號;;
避免在VS2013中警告FS0058。
啊;我忘了編譯器在這裏做魔術;我在想運行時。非常有意義的是,這隻適用於編譯時可用的字符串! –
是從字符串到TextWriterFormat的隱式轉換 F#專門用於printf的東西,還是可以用自己的類型來做到這一點? –
「非常有意義的是,這隻適用於編譯時可用的字符串!」 - 好吧,不。 'let printsd fmt = Printf.TextWriterFormat int - > unit> fmt |> printfn'工作。如果fmt沒有正確的格式說明符,它會在運行時失敗。 –