我是新手学习F#并编写一个简单的控制台应用程序,用户输入一个距离值,我想要一些验证以确保输入是一个数字。它还需要确保它是一个数字,如果不是,请告诉用户并重新开始。这就是我到目前为止所做的:
let distance = 0
while distance = 0 do
System.Console.WriteLine("How far do you want to travel?")
let answer = System.Console.ReadLine()
try
let distance = System.Int32.Parse(answer)
if distance < 0 then
let distance = 0
printfn "Can't use negative numbers"
elif distance = 0 then
printfn "Can't travel a distance of 0"
else
printfn "You are about to travel %A" distance
finally
let distance = 0
printfn "Invalid distance format"
这就是出现的问题:
在这个例子中,我想要发生的是“无效距离格式”到不是,并且它会移动到应用的下一部分。
如果distance
无法通过System.Int32.Parse(answer)
即使try-finally是完全错误的方法,还有什么办法呢?
提前致谢
答案 0 :(得分:7)
你想要的是try...with
try
let distance = System.Int32.Parse(answer)
. . . . .
with
| _ as ex -> printfn "Invalid Distance Format"
http://fsharpforfunandprofit.com/posts/exceptions/
您也可以执行类似
的操作...
let attemptedConvert = Int32.TryParse(answer)
let success,convertValue = attemptedConvert
if success then
//other stuff here
else
printfn "Invalid Number Format"
这样就不会抛出异常,如果条目成功转换,您仍然可以进行验证。
如下所述,异常可能是比其他替代方案更昂贵的操作,应进行评估以查看是否会导致不必要的开销。但是,与任何流程一样,应根据具体情况进行评估。
答案 1 :(得分:3)
在你学习的过程中,我会通过做这样的事情来解决这个问题。
它使用了对于处理'null'情况(即没有输入)有用的选项类型。它还使用F#模式匹配,这是使用if,else,elif等的非常强大的替代方法。
//see here - http://fsharpforfunandprofit.com/posts/the-option-type/
let tryParseOption intStr =
try
let i = System.Int32.Parse intStr
Some i
with _ -> None
type Ask =
static member Askdistance (?text)=
let text = defaultArg text ""
printfn "%s" text
System.Console.WriteLine("How far do you want to travel?")
let distance = tryParseOption (System.Console.ReadLine())
match distance with
|None -> Ask.Askdistance("Invalid format distance provided")
|Some(a) when a <0 -> Ask.Askdistance("Can't use negative numbers")
|Some(a) when a =0 -> Ask.Askdistance("Can't travel a distance of 0")
|_ -> printfn "You are about to travel %A" distance.Value
ignore()
//this will keep asking you to input a distance until you put in a correct value (i.e. a positive integer value. Note it will reject a floating point input).
Ask.Askdistance()
答案 2 :(得分:1)
虽然其他答案是正确的,但这是另一种方法:
open System
let rec travel() =
printfn "How far do you want to travel?"
let d = Console.ReadLine()
match Int32.TryParse d with
| false, _ ->
printfn "Invalid distance format '%s'" d
travel()
| _, 0 ->
printfn "Can't travel a distance of 0"
travel()
| _, d when d < 0 ->
printfn "Can't use negative number %i" d
travel()
| _, d ->
printfn "You are about to travel %i" d
travel()
在我看来,这有以下优点:
printfn
vs Console.WriteLine
)我同意,学习一门新语言应该探索解决方案空间。但是选择一种简洁,优雅的方式。
我的答案的其他一些方面可能是固执己见。你可能想要
true
代替_
。重新排序案例,例如拥有'快乐路径'首先类似于try...catch
:
open System
let rec travel() =
printfn "How far do you want to travel?"
let d = Console.ReadLine()
match Int32.TryParse d with
| true, d when d > 0 ->
printfn "You are about to travel %i" d
| true, 0 ->
printfn "Can't travel a distance of 0"
travel()
| true, _ ->
printfn "Can't use negative number %i" d
travel()
| _ ->
printfn "Invalid distance format '%s'" d
travel()
travel()
另一种方法是从控制台分离阅读和旅行:
使用始终返回int
的阅读功能:
open System
let rec readInt() =
let d = Console.ReadLine()
match Int32.TryParse d with
| true, d ->
d
| _ ->
printfn "Invalid distance format '%s'" d
readInt()
let rec travel() =
printfn "How far do you want to travel?"
let d = readInt()
if d > 0 then
printfn "You are about to travel %i" d
elif d = 0 then
printfn "Can't travel a distance of 0"
travel()
else
printfn "Can't use negative number %i" d
travel()
travel()
使用可能失败的阅读功能:
open System
let rec readInt() =
let d = Console.ReadLine()
match Int32.TryParse d with
| true, d -> Some d
| _ -> None
let rec travel() =
printfn "How far do you want to travel?"
match readInt() with
| Some d when d > 0 ->
printfn "You are about to travel %i" d
| Some d when d = 0 ->
printfn "Can't travel a distance of 0"
travel()
| Some d ->
printfn "Can't use negative number %i" d
travel()
| None ->
printfn "Invalid distance format '%s'" d
travel()
travel()