F# 简单地解析命令行参数

F# 简单地解析命令行参数,f#,F#,我想使用下面的代码来限制只有一个参数。但是,我在first::NIL中遇到了以下错误 Error 1 This expression was expected to have type string [] but here has type 'a list 错误1此表达式应具有类型 字符串[] 但这里有一种类型 "名单", [] 让主argv= 将argv与 |第一:无-> .... 先做点什么 |->failwith“必须只有一个参数。” 命令行参数作为数组而不

我想使用下面的代码来限制只有一个参数。但是,我在
first::NIL
中遇到了以下错误

Error 1 This expression was expected to have type string [] but here has type 'a list 错误1此表达式应具有类型 字符串[] 但这里有一种类型 "名单",
[]
让主argv=
将argv与
|第一:无->
.... 先做点什么
|->failwith“必须只有一个参数。”

命令行参数作为数组而不是列表传递

如果只需要一个参数,请执行以下操作:

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

如接受答案中所述,入口点的“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
[]
让主参数=
设arglist=args |>List.ofSeq
将arglist与
|第一::[]->
//用“第一个”做点什么
|->//捕获无参数和多参数情况
printfn“用法:
//打印使用信息
编辑: 至于更复杂的例子,有两种方法。当然,您可以在匹配中添加更复杂的事例,也可以以递归方式解析参数列表,以构建表示选项和参数的对象。后者会变得有点太复杂,无法在这里进行匹配,但作为一些更复杂匹配情况的示例,下面是一些与最近的一些工作相关的代码,其中可执行文件接受“命令”对目标文件进行操作,并且每个命令都有不同的进一步参数(每个命令调用一个函数,为了简洁起见,我省略了该函数的实现)

[]
让主参数=
设arglist=args |>List.ofSeq
将arglist与
|目标::“列表”::[]->
列表内容目标
|目标::“删除”::名称::[]->
removeContent目标名称
|目标::“添加”::名称::[]->
addContent目标名称
|目标::“addall”::名称->
名副其实
addContent目标名称
|->//捕获上述未涵盖的案例
printfn“用法:
//打印使用信息

解析单个命令的活动模式如何,在出现故障时返回一个指示“无”的选项,以及一些包含已恢复参数内容的选项,可能嵌套在它们自己的专用类型中。将“argv”转换为“string list”由于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
type Cmd1Parms=。。。。
键入Cmd2Parms=。。。。
让PerformMcMD1 cmd1Parms=。。。
让PerformMcMD2 cmd2Parms=。。。
让commandNotFound argL=。。。
let(| ParseForCmd1 | |)argL:Cmd1Parms选项=。。。。
let(| ParseForCmd2 | |)argL:Cmd2Parms选项=。。。。
[]
让主argv=
设argL=List.ofSeq argv
将argL与
|ParseForCmd1 cmd1Parms->performCmd1 cmd1Parms
|ParseForCmd2 cmd2Parms->performCmd2 cmd2Parms
|->commandNotFound argL

我认为数组可以隐式转换为list。@dc7a9163d9在F#中,除了向对象上的方法传递参数外,没有隐式转换。有关详细信息,请参阅此处:如果数组作为参数传递给需要序列的函数,则可以隐式转换为序列。请注意,这适用于转换ing to sequence(IEnumerable),而不是强制转换为list。这是因为数组实现了IEnumerable。请注意,F#“list”(及其良好的语法支持)是一种特定于F#(实现单链接列表)的类型,它与IEnumerable不同(尽管它实现了它).这是我发现的第一个明确说明参数作为(数组)传入的类型的地方.我的意思是,我本可以猜到,但是到目前为止,F#的文档对我来说并不像C#那么容易。谢谢。你能举一个更复杂的解析的例子吗?它可能有用。我想知道F#是否需要使用第三方参数库,或者它本身就足够强大,所以它不是必需的。如果你想要第三方库,我喜欢使用F#cmd线条工具。
[<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
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