只需解析命令行参数即可

时间:2013-11-27 20:10:10

标签: f#

我想使用以下代码来限制只有一个参数。但是,我在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."

3 个答案:

答案 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