F # Соответствующий изменяемый объект (строка) - PullRequest
0 голосов
/ 16 сентября 2010

Вот полный код:

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 ' Я не уверен, где я совершил ошибку.

Ответы [ 3 ]

4 голосов
/ 16 сентября 2010

Две вещи.

  1. В F # привязки могут быть скрыты. В частности, в ваших match, когда вы используете game1, game2 и game3 в шаблонах, вы фактически объявляете новые привязки с этими именами. Следовательно, первый шаблон всегда будет совпадать и просто назначит любое значение, которое вы пытаетесь сопоставить с ним, новой привязке game1, прежде чем вычислять правую часть.

    Один из способов обойти это - объявить привязки gameN с атрибутом [<Literal>] (но учтите, что они также должны начинаться с заглавных букв, чтобы работать как константы):

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

    Теперь вы можете использовать Game1 в сопоставлении с образцом, и он будет работать так, как вы ожидаете.

  2. Возможно, вы знаете об этом, но на самом деле вы нигде не обновляете привязку gameprint, так что она будет иметь одинаковое значение во всей вашей программе, и нет смысла ее изменять .

3 голосов
/ 16 сентября 2010

См. F # для двух значений для объяснения.

При сравнении с несколькими не буквальными значениями я просто использовал бы if-then-else

if gameprint = game1 then ...
elif gameprint = game2 then ...
...
1 голос
/ 16 сентября 2010

Возможно, что-то более похожее на это позволит вам сделать его более расширяемым (если вы заполняете список игр во время выполнения) ... извините, коды немного поспешили, я пытаюсь подготовиться к работе:

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)
...