我刚开始深入研究一些编程并决定使用F#。作为练习,我试图将我在.bat中创建的脚本转换为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
我知道如果它到达最后一个“其他”,我会遗漏一些让它再次运行的东西;我收到了这些错误:
表达式的类型应为'unit',但类型为'string'。使用'ignore'丢弃表达式的结果,或'let'将结果绑定到名称。
错误1此表达式的类型为int,但此处的类型为字符串19 21
错误2此表达式的类型为int,但此处的类型为字符串20 23
错误3此表达式的类型为int,但此处的类型为字符串21 23
错误4此表达式应具有类型字符串,但此处具有类型单元22 17
警告5此表达式应为“unit”类型,但类型为“string”。使用'ignore'丢弃表达式的结果,或'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'
如果有一种我不了解的功能性方法,我当然希望学习: - )
提前致谢!
答案 0 :(得分:7)
您第一次尝试的最大问题是您正在将string
的输入解析为int
,但之后您尝试对字符串进行模式匹配。使用1
,2
和3
代替"1"
,"2"
和"3"
将解决该问题,但之后您将成为与你的第二次尝试大致相同。
你的第二次尝试几乎可以解决,但是F#告诉你你没有在所有分支中使用一致的返回类型:在前三种情况下你返回一个字符串,但在最后一种情况下你不是回来什么。在这种情况下,你需要做的只是循环,编译器会很高兴:
let rec getGame() =
match Int32.Parse(stdin.ReadLine()) with
| 1 -> "Assassin's Creed"
| 2 -> "Crysis"
| 3 -> "Mass Effect"
| _ -> printf "Temp"; getGame()
我会做更多这样的事情:
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()
答案 1 :(得分:0)
感谢非常及时的回复!我从昨天开始就一直在努力克服这个障碍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'这些笔记适用于任何对细节感兴趣的新人。