2010-09-15 84 views
3

我剛開始深入研究一些編程,並決定使用F#。作爲練習,我試圖將我在.bat中創建的腳本轉換爲F#。我在創建一個循環函數時遇到了困難,它執行的不止一件事情。這是來自這個循環的舊腳本的代碼。F#創建具有多種功能的單個循環

:Select 
cls 
echo. 
echo Which Game? 
echo. 
echo 1. Assassin's Creed 
echo 2. Crysis 
echo 3. Mass Effect 
echo. 
echo. 
set/p "game=>" 
if /I %game%==1 goto Creed 
if /I %game%==2 goto Crysis 
if /I %game%==3 goto Mass 
echo. 
echo Invalid selection! 
echo. 
echo. 
pause 
goto Select 

我試圖讓在F#的同樣功能的代碼看起來像這樣至今:

let rec gameprint gameselect = 
    printfn "Which Game?\n\n 1.%s\n 2.%s\n 3.%s\n\n\n" game1 game2 game3 
    let mutable gameselect = Int32.Parse(stdin.ReadLine()) 
    if gameselect = "1" then game1 
    elif gameselect = "2" then game2 
    elif gameselect = "3" then game3 
    else printf "temp" 
    Console.Clear 

我知道我失去了一些東西,告訴它是否達到它再次運行最後的「其他」;我得到這些錯誤:

該表達式應該有類型'單位',但類型'字符串'。使用'忽略'放棄表達式的結果,或'let'將結果綁定到名稱。

錯誤1此表達預期具有int類型,但這裏的類型爲字符串19 21

錯誤2預計該表達式爲具有int類型,但這裏有類型串20 23

錯誤3該表達預計具有int類型,但這裏有類型串21 23

錯誤4,預計該表達式爲具有類型字符串,但這裏有類型單元22 17

警告5此表達式應該公頃ve類型的「單位」,但類型爲「字符串」。使用'忽略'放棄表達式的結果,或'let'將結果綁定到名稱。 19 5

我寧願使用這樣的方法(非常不完整):

let rec getGame() = 
    match Int32.Parse(stdin.ReadLine()) with 
    | 1 -> "Assassin's Creed" 
    | 2 -> "Crysis" 
    | 3 -> "Mass Effect" 
    | _ -> printf "Temp" 

但我發現了:

錯誤1,預計這種表達有字符串類型,但在這裏有型單元36 19

而且我不知道我怎麼會循環並使其上的「printf」和「Console.Clear」

如果有I D功能更強大的方法不知道,我一定會喜歡學習:-)

在此先感謝!

回答

7

您第一次嘗試的最大問題是您將string的輸入解析爲int,但您嘗試對字符串進行模式匹配。使用1,23而不是"1","2""3"可以解決這個問題,但是這樣你就會和第二次嘗試的時間基本持平。您的第二次嘗試幾乎可行,但F#告訴您,您並未在所有分支中使用一致的返回類型:在前三種情況下,您返回的是字符串,但在最後一種情況下,您是不返回任何東西。所有你需要做的就是在這種情況下循環,編譯器會很高興:對於非常迅速的反應

type Game = Creed | Crysis | Mass 

let rec getGame() = 
    printfn "Which Game?\n\n 1.%A\n 2.%A\n 3.%A\n\n" Creed Crysis Mass 
    match stdin.ReadLine() |> Int32.TryParse with 
    | true,1 -> Creed 
    | true,2 -> Crysis 
    | true,3 -> Mass 
    | _ -> 
    printfn "You did not enter a valid choice." 
    // put any other actions you want into here 
    getGame() 
+0

@ Abraxas000:我看到這是你的第一個問題。歡迎!如果你覺得它確實回答你的問題,接受答案是很好的禮儀。這可以通過點擊答案左側的複選框大綱來完成。 – 2010-09-15 23:19:19

0

感謝:

let rec getGame() = 
    match Int32.Parse(stdin.ReadLine()) with 
    | 1 -> "Assassin's Creed" 
    | 2 -> "Crysis" 
    | 3 -> "Mass Effect" 
    | _ -> printf "Temp"; getGame() 

我會做一些更喜歡這個!我一直對這個障礙,因爲昨天的xD

當前代碼執行:

#light 
open System 
open System.IO 
//Simplify pausing 
let pause() = Console.ReadLine() 
//Identify the durrent drive letter associated with the flash drive for use 
//when saving/deleting Save Data 
let drive = System.IO.Directory.GetDirectoryRoot(System.IO.Directory.GetCurrentDirectory()) 
printfn "You're using the %s drive.\n\n" drive 

//Identify the games to save 
let game1 = "Assassin's Creed" 
let game2 = "Crysis" 
let game3 = "Mass Effect" 

//Identify which game to Save/Load the data for 
let rec getGame() = 
    printfn "Which Game?\n\n 1.%s\n 2.%s\n 3.%s\n\n" game1 game2 game3 
    match Int32.TryParse(stdin.ReadLine()) with 
    | true,1 -> game1 
    | true,2 -> game2 
    | true,3 -> game3 
    | _ -> 
    printfn "You did not enter a valid choice." 
    //The '_' is to ignore the result of Console.Readline() without binding it to anything 
    //that way you can re-use the same line as many times as you like 
    let _ = pause() 
    Console.Clear() 
    getGame() 

//Print the selected game 
let gameprint = getGame() 
printf "You have chosen %s\n\n" gameprint 
let _ = pause() 

我掏出:

Type Game = Creed | Crysis | Mass 

,因爲它與getGame的結果「printf」式干擾()

這些筆記適用於任何對細節感興趣的新人。

+0

請注意,您可以在printf格式字符串中使用'「%A」來打印任意類型的值(而不是打印字符串的「%s」')。 – kvb 2010-09-15 20:54:53