2010-09-16 45 views
0

這是迄今爲止全碼:F#匹配可變對象(字符串)

module clean 
#light 
open System 
open System.IO 
let pause() = Console.ReadLine() 
let drive = System.IO.Directory.GetDirectoryRoot(System.IO.Directory.GetCurrentDirectory()) 
printfn "You're using the %s drive.\n\n" drive 

let game1 = "Assassin's Creed" 
let game2 = "Crysis" 
let game3 = "Mass Effect" 

let local1 = "\%APPDATA\%\\Ubisoft\\Assassin's Creed\\Saved Games\\" 
let local2 = "\%USERPROFILE\%\\Documents\\My Games\\Crysis\\SaveGames\\" 
let local3 = "\%USERPROFILE\%\\Documents\\BioWare\\Mass Effect\\Save\\" 

let roam1 = drive + "Saves\\Abraxas\\" + game1 + "\\" 
let roam2 = drive + "Saves\\Abraxas\\" + game2 + "\\" 
let roam3 = drive + "Saves\\Abraxas\\" + game3 + "\\" 




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." 
    let _ = pause() 
    Console.Clear() 
    getGame() 

let mutable gameprint = getGame() 
printf "You have chosen %s\n\n" gameprint 

let roaming = 
    match gameprint with 
    | game1 -> roam1 
    | game2 -> roam2 
    | game3 -> roam3 
    | _ -> "test" 

printf "Roaming set to %s\n\n" roaming 

let local = 
    match gameprint with 
    | game1 -> local1 
    | game2 -> local2 
    | game3 -> local3 
    | _ -> "test" 

printf "Local set to %s\n\n" local 

printf "Check gameprint %s" gameprint 

在用於設置漫遊和本地對象的部分,它告訴我,它永遠不會匹配比「其他任何的Game1' 。

我做了'printf'來檢查匹配本地和漫遊對象之前和之後......遊戲打印在兩個printf命令中都正確顯示,但與除game1之外的任何其他內容都匹配...... I我不確定我犯了什麼錯誤。

+0

這應該仍然堅持乾的原則。我不會在任何地方重複任何字符串聲明(我沒有將gamen嵌入到localn中,因爲它不僅僅是gamen,即localn中的更改,不同的遊戲很少會有類似的結構)。 DRY原則的一部分:「邏輯上相關的元素全部可預測和統一地變化」。如果要改變Localn,它永遠不會改變。 – Abraxas000 2010-09-17 13:41:16

回答

4

兩件事情。

  1. 在F#中,綁定可以被隱藏。特別是,在您的match中,當您使用game1,game2game3模式時,實際上您將聲明新的與這些名稱的綁定。因此,第一個模式將始終匹配,並且只會在評估右側之前將您嘗試匹配的值賦予新綁定game1。要解決此

    的一種方法是用[<Literal>]屬性來聲明冠盟綁定(但請注意,他們也必須以大寫字母爲常數工作):

    [<Literal>] let Game1 = "Assassin's Creed"

    現在你可以使用模式匹配中的Game1,它將按照您的預期工作。

  2. 您可能已經意識到了這一點,但實際上並未實際更新gameprint綁定,因此它將在整個程序中設置爲相同的值,並且它沒有任何可變性。

+0

1.完美,感謝您的幫助!我稍後會在代碼中改變它,所以它需要是可變的。感謝您檢查。 – Abraxas000 2010-09-16 13:29:50

3

有關說明,請參見F# matching with two values

當對一些非字面值進行比較,我只是使用if-then-else的

if gameprint = game1 then ... 
elif gameprint = game2 then ... 
... 
1

也許東西多一點這樣將允許你做出更擴展(如果你的填充在運行遊戲列表)...對不起有點衝,我試圖讓準備好碼工作:

open System 
type Game = {Title:string; local:string; roam:string} 

let game1 = { 
    Title= "Assassin's Creed"; 
    local = "\%APPDATA\%\\Ubisoft\\Assassin's Creed\\Saved Games\\"; 
    roam = "Saves\\Abraxas\\\Assassin's Creed\\" 
} 
let game2 = { 
    Title= "Crysis"; 
    local = "\%USERPROFILE\%\\Documents\\My Games\\Crysis\\SaveGames\\"; 
    roam = "Saves\\Abraxas\\\Crysis\\" 
} 
let games = [game1; game2] 
let printGamelListItem i g = printfn "%i: %s" i g.Title 

let printChoice() = 
    printfn "Which Game?\n" 
    games |> List.fold (fun acc g -> 
          printGamelListItem acc g 
          acc+1) 1 
    |> ignore 

let rec getGame() = 
    printChoice() 
    match Int32.TryParse(Console.ReadLine()) with 
    |true, x when x <= games.Length -> games.[x-1] 
    | _ -> 
     printfn "You did not enter a valid choice." 
     let _ = Console.ReadLine() 
     Console.Clear() 
     getGame() 

let selection = getGame() 
printfn "Roaming set to: %s" (selection.roam) 
printfn "Local set to: %s" (selection.local) 
+0

感謝您的有趣演繹,當我完成後,我一定會回頭看看這個,但是這會稍微複雜一點,然後我在第四天就準備好了。雖然我確實喜歡這個方向: - ) – Abraxas000 2010-09-16 13:46:14