2009-06-24 68 views
7

我在玩F#(Visual Studio 2010 beta 1),我寫了一個小小的控制檯腳本,要求用戶輸入2個數字和一個運算符,然後執行它。 它工作正常,除了一個微小的,但煩人的事情:有時我的printfn指令被忽略。我在代碼中放置了斷點來確定情況。F#奇怪的printfn問題

的代碼片段:

let convert (source : string) = 
    try System.Int32.Parse(source) 
    with :? System.FormatException -> 
     printfn "'%s' is not a number!" source; 
     waitForExitKey(); 
     exit 1 

let read = 
    printfn "Please enter a number."; 
    System.Console.ReadLine 

let num1 : int = read() |> convert // the printfn in the read function is run... 
let num2 : int = read() |> convert // ... but here is ignored 

這當然不是完整的源代碼,但我認爲那將是足夠的。如果你需要完整的源代碼,請告訴我。

所以我的問題很簡單:什麼導致與printfn這個問題?難道我做錯了什麼?

由於提前, ShdNx

回答

15

This page有什麼事情的部分解釋,但簡短而親切的版本是F#將如果不帶參數,則在聲明上執行任何值。

let read = 
    printfn "Please enter a number." 
    System.Console.ReadLine 

由於read不採取任何參數,其上聲明立即執行和函數的返回值結合所述標識符read

順便說一下,您的返回值恰巧是(unit -> string)類型的函數。這是因爲F#自動地如果它們沒有傳遞所有參數,它會自動curries functionsReadLine需要一個單位參數,但由於它沒有傳遞,所以實際上將read綁定到ReadLine函數本身。

的解決方案如下:

let read() = // read takes one unit parameter 
    printfn "Please enter a number." 
    System.Console.ReadLine() // pass paramter to ReadLine method 

由於read有一個參數,其重新評估的每個時間其調用。此外,我們將參數傳遞給ReadLine,否則我們只會將ReadLine函數作爲值返回。

+0

非常感謝!不幸的是,雷更快,所以我接受了他的答案。但我很高興你明確表達了這一點。再次感謝! – ShdNx 2009-06-24 17:43:41

7

我明白,這可能會造成混淆。在你的例子中,printfn運行得比你想象的要早。即使沒有read()的呼叫,它也會實際執行,即註釋掉最後兩行,並且仍然會看到正在打印的消息。

我覺得你的意圖是這樣的:

let read() = 
    printfn "Please enter a number."; 
    System.Console.ReadLine() 

這將創建一個「可重複使用的」函數,而不是結合的標識符的功能在你原來的例子。

一點題外話,在這裏使用分號是可選的,所以你可以這樣寫:

let read() = 
    printfn "Please enter a number." 
    System.Console.ReadLine() 
+0

非常感謝,我想我現在明白了! 我使用分號,因爲我在每行之後自動添加一個分號,如果我看不到任何...,它會困擾我:-) – ShdNx 2009-06-24 17:42:43