2013-11-27 138 views
2

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

如果你想有一个第三方的lib,我喜欢用[UnionArgParser(https://github.com/eiriktsarpalis/UnionArgParser)为F#CMD行工具。 –

回答

4

命令行参数作为数组,不是列表通过。

做这样的事情,如果你希望只有一个参数:

match argv with 
| [|first|] -> 
    // .... do something with first 
| _ -> failwith "Must have only one argument." 
+0

我想数组可以隐式列表。 – ca9163d9

+0

@ dc7a9163d9在F#中,除了在将参数传递给对象上的方法时,不存在隐式转换。请参阅此处了解更多详细信息:http://msdn.microsoft.com/en-us/library/vstudio/dd233220.aspx – mydogisbox

+1

如果将数组作为参数传递给期望序列的函数,则可以隐式地将数组转换为序列。请注意,这适用于投射顺序(IEnumerable <>),而不是投射到列表。这是因为数组实现了IEnumerable <>。请注意,F#“list”(具有所有其良好的语法支持)是F#特定的类型(实现单向链接列表) - 它与IEnumerable(尽管它实现它)不同。 –

3

作为公认的答案中提到的“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 
+0

谢谢。你能举一个更复杂的解析的例子吗?它可以是有用的。我想知道f#是否需要使用一些第三方参数库,或者它没有必要,因为它本身足够强大。 – ca9163d9

0

如何解析各个命令,返回一个选项,指示无失败和一些与恢复的内容活动模式参数,可能按照它们自己的专用类型进行设置。由于F#中的列表语法方便,将“argv”转换为“字符串列表”仅仅是一种方便的行为。注意:这里有很多类型的注释通常是不必要的。

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