使用玩具示例来验证输入参数,并在无效时发出错误消息。到目前为止,我有:
let usage =
printfn "Usage: %s " (Process.GetCurrentProcess().ProcessName)
exit -1
let test what date id flag =
let date =
match DateTime.TryParse date with
| (true, d) -> Some d
| _ -> usage
let id =
match Int32.TryParse id with
| (true, int) -> Some int
| _ -> usage // error here
0
[<EntryPoint>]
let main argv =
printfn "%A" argv
match argv with
| [| what; date; id; flag |] -> test
| _ -> usage
但这会产生错误:
错误1类型不匹配。期待一个 int选项但是给出了一个 DateTime选项类型&#39; int&#39;与类型&#39; DateTime&#39;
不匹配
从哪里获取DateTime类型?第一场比赛?但那么,为什么?在没有出现类型错误的情况下编写catch-all错误处理程序的正确方法是什么?
答案 0 :(得分:2)
&#34;问题1:
let usage =
这不是一个功能。你最想要的是
let usage () =
你必须像这样调用这个函数。
usage ()
问题2:
错误的原因是基于类型推断,用法返回DateTime选项。
这两行中的第一行是编译器确定匹配表达式将返回DateTime选项的位置。第二行是编译器推断&#34;用法&#34;必须也是DateTime选项,因为匹配表达式返回DateTime选项。
| (true, d) -> Some d
| _ -> usage
如何使用成为DateTime选项?因为您使用&#34;退出-1&#34;,并且退出的签名是int-&gt;&#39; T,因此&#34; usage&#34;实际上,编译器会强制它根据类型推断返回特定类型。它被强制输入&#34; DateTime选项&#34;,这不是你想要的。为了防止这种情况,您可以声明预期的结果使用类型,或者可以显式返回您想要的值。我会在这里做两件事来说明这一切。
let usage () : unit =
printfn "Usage: %s " (Process.GetCurrentProcess().ProcessName)
exit -1
()
现在&#34;用法&#34;已被锁定为unit-&gt;单位的签名,这简化了我们的进一步工作。
问题3:
F#是一种功能语言,而不是命令式语言。 &#34;用法&#34;功能相当成问题。我建议你用&#34; failwith&#34;来替换它。相反,并用&#34;尝试&#34;捕获错误在&#34; main&#34;,如下所示。另一种选择是&#34;使用&#34;返回&#; T,与&#34;相同&#34;是的,如果你真的希望能够在任何地方终止程序。不推荐,因为这种使用会让你在这个阶段难以理解。然后,您的程序将退出,但不会显示可能出错的迹象。更好地处理如下所示的预期和意外异常,并从主函数中彻底终止。
let test what date id flag =
let date =
match DateTime.TryParse date with
| (true, d) -> Some d
| _ -> failwith "Error 1 here."
let id =
match Int32.TryParse id with
| (true, int) -> Some int
| _ -> failwith "Error 2 here."
()
let main argv =
try
match argv with
| [| what; date; id; flag |] -> test what date id flag
| _ -> failwith "Error 3 here."
0
with ex ->
printfn "Error: %s" ex.Message
printfn "Usage: %s" (Process.GetCurrentProcess().ProcessName)
-1