我想使用以下代码来限制只有一个参数。但是,我在first :: NIL
收到了以下错误?
Error 1 This expression was expected to have type string [] but here has type 'a list
[<EntryPoint>]
let main argv =
match argv with
| first :: NIL ->
.... do something with first
| _ -> failwith "Must have only one argument."
答案 0 :(得分:7)
命令行参数作为数组传递,而不是列表。
如果您只想要一个参数,请执行以下操作:
match argv with
| [|first|] ->
// .... do something with first
| _ -> failwith "Must have only one argument."
答案 1 :(得分:4)
正如在接受的答案中所提到的,入口点的“args”参数是一个数组,而不是一个列表,所以你不能将它与列表匹配的语法一起使用。
如上所述,您可以将参数转换为实际列表,并将其用于匹配,而不是在数组上进行匹配。我发现了一个非常有用的方法来处理命令行参数(尽管对于你的示例案例可能有点过分)。举个例子:
[<EntryPoint>]
let main args =
let arglist = args |> List.ofSeq
match arglist with
| first :: [] ->
// do something with 'first'
| _ -> // catches both the no-argument and multi-argument cases
printfn "Usage : "
// print usage message
编辑: 至于更复杂的例子,有两种方法可以从这里开始。您当然可以在匹配中添加更复杂的案例,或者您可以以递归方式解析参数列表以构建表示选项和参数的对象。后者在这里有点过于复杂,但作为一些更复杂的匹配案例的例子,这里有一些与最近的工作有关的代码,其中可执行文件接受“命令”来操作目标文件,以及每个命令有不同的进一步的参数(每个命令调用一个函数,我为了简洁而遗漏了它的实现)
[<EntryPoint>]
let main args =
let arglist = args |> List.ofSeq
match arglist with
| target :: "list" :: [] ->
listContent target
| target :: "remove" :: name :: [] ->
removeContent target name
| target :: "add" :: name :: [] ->
addContent target name
| target :: "addall" :: names ->
for name in names do
addContent target name
| _ -> // catches cases not covered above
printfn "Usage : "
// print usage message
答案 2 :(得分:0)
用于解析单个命令的Active Patterns如何,返回一个选项,指示失败时为None,一些选项包含已恢复参数的内容,可能位于各自的专用类型中。转换&#34; argv&#34;到&#34;字符串列表&#34;由于F#中列表语法的方便性,它仅仅是一种便利行为。注意:这里有很多类型注释通常是不必要的。
type Cmd1Parms = ....
type Cmd2Parms = ....
let performCmd1 cmd1Parms = ...
let performCmd2 cmd2Parms = ...
let commandNotFound argL = ...
let (|ParseForCmd1|_|) argL : Cmd1Parms option = ....
let (|ParseForCmd2|_|) argL : Cmd2Parms option = ....
[<EntryPoint>]
let main argv =
let argL = List.ofSeq<string> argv
match argL with
| ParseForCmd1 cmd1Parms -> performCmd1 cmd1Parms
| ParseForCmd2 cmd2Parms -> performCmd2 cmd2Parms
| _ -> commandNotFound argL