I'm trying to use F# and System.CommandLine to make a little CLI tool. A command can have a handler callback that is called when the command is used. Usually one can define several flags for a command and the name of the flag is used to bind to an argument of the handler function with the same name.
Example
myApp foo --a
will call the handler for the foo
command
let handler (a: bool) (b: bool) = // a should be true, b should be false
...
However this doesn't work and both a
and b
are false when I bind the handler that is a let binding:
let fooCommand = Command ...
fooCommand.Handler <- CommandHandler.Create handler
// will call handler false false
But, when I use a lambda directly it works fine and the function arguments have the correct values
let fooCommand = Command ...
fooCommand.Handler <- CommandHandler.Create (fun (a: bool) (b: bool) -> handler a b)
// will call handler true false
Why is that? Why does the handler work as a lambda but not as a let binding?
Here is a MRE
#r "nuget: System.CommandLine, 2.0.0-beta1.21308.1"
open System.CommandLine
open System.CommandLine.Invocation
open System.CommandLine.Parsing
let opts = [Option<bool>([|"--a"|]); Option<bool>([|"--b"|])]
let fooCmd = Command("foo", "")
List.iter fooCmd.AddOption opts
let barCmd = Command("bar", "")
List.iter barCmd.AddOption opts
let handler (a: bool) (b: bool) =
printfn "%A" {| a = a; b = b|}
fooCmd.Handler <- CommandHandler.Create handler
barCmd.Handler <- CommandHandler.Create (fun (a: bool) (b: bool) -> handler a b)
let root = RootCommand("")
root.Add fooCmd
root.Add barCmd
printfn "foo --a: "
root.Invoke("foo --a")
printfn "bar --a: "
root.Invoke("bar --a")
which prints
foo --a:
{ a = false
b = false }
bar --a:
{ a = true
b = false }
Aucun commentaire:
Enregistrer un commentaire