6

我正在学习 F# 并发现我正在写一些有用但我并不完全理解的东西。这是一个例子

let processArgs args =
    match args with
    | null
    | [||]          -> [fun() -> getCredentials(); home 20; mentions 20; messages 20]
    | [|"-h"|] 
    | [|"-?"|]      -> [showHelp]
    | [|"-reset"|]  -> [clearAllSettings]
    | _             -> [fun() -> printfn "%s" (String.Join(" ", args))]

[<EntryPoint>]
    let main (args:string[]) =
    try
        let actions = processArgs args
        List.iter (fun action -> action()) actions
        0
    finally
        Console.ResetColor()
        Console.CursorVisible <- true

getCredentials、home、mentions、messages、showHelp 和 clearAllSettings 方法都是简单的函数,可以按照您的预期进行操作。(是的,它是一个 twitter 客户端,这不是新的“Hello World”演示吗?)

该行:

[fun() -> getCredentials(); home 20; mentions 20; messages 20]

像我想要的那样工作。它调用 getCredentials,然后是 home,然后是提及,然后是消息

从我的角度来看,分号就像一个语句分隔符。我以前没有见过这样的描述。这就是这里发生的事情吗?

有没有更惯用的方式来写这个(换句话说,一个经验丰富的 F# 程序员看到这个会在地板上大笑)?

更多信息:我最初的意图是创建一个操作列表,然后在我发现选项时添加操作。在 C# 中,我通常会使用 List<Action>() 来执行此操作。分号的事情让我感到惊讶,因为最初我试图这样写:

[getCredentials; home 20; mentions 20; messages 20]

但是编译器不喜欢它。

4

1 回答 1

3

当你写:

[fun() -> getCredentials(); home 20; mentions 20; messages 20]

编译器创建一个列表,其中只有一个元素是 type 的函数unit -> unitS1 ; S2是 S1 类型为 时的序列组合unit,依次执行 S1 和 S2 并返回 S2 的结果。所以,三个功能home,居然都有签名。mentionsmessagesint -> unit

如果你想创建一个包含 4 个不同函数的列表,它应该是:

[ getCredentials; // ; is optional
  fun () -> home 20; 
  fun () -> mentions 20; 
  fun () -> messages 20 ]

这些函数用空格分隔以避免混淆使用;作为列表分隔符和序列组成。

由于您的示例所有列表都只有一个元素,因此可以简化很多:

let processArgs = function
    | [||]          -> getCredentials(); home 20; mentions 20; messages 20
    | [|"-h"|] 
    | [|"-?"|]      -> showHelp()
    | [|"-reset"|]  -> clearAllSettings()
    | args          -> printfn "%s" (String.Join(" ", args))

[<EntryPoint>]
let main (args:string[]) =
  try
    processArgs args
    0
  finally
    Console.ResetColor()
    Console.CursorVisible <- true
于 2012-05-22T02:33:49.773 回答