'Matching command line args
Starting out learning F#. Want to make a simple program that just tells me what it found in the command line args. I have:
[<EntryPoint>]
let main argv =
printfn "%A" argv
match argv with
| [] -> 42
| _ -> 43
But this gives errors. If I hover over argv I see:
val argv : string[]
which is what I would have expected (a list of strings). However the first match expression has an error:
Error 1 This expression was expected to have type string [] but here has type 'a list
Basically I just want to match on an empty argument list (an empty list of strings). What's the right way to do that?
I should add: I don't just want a solution (though that would be nice). I also want to understand what the compiler is looking for here that I'm not giving it.
Solution 1:[1]
It might be confusing since []
literal is used to signify an empty list, but type string []
is an array of strings rather than a list.
You can pattern match against an array like this:
[<EntryPoint>]
let main argv =
printfn "%A" argv
match argv with
| [||] -> 42
| _ -> 43
Like many seemingly inconsistent things in F#, this is a result of its dual heritage.
In OCaml, you'd use int list
and int array
for the types, [1;2;3]
and [|1;2;3|]
for the values respectively. But in C#/.NET, square brackets as in int[]
are the way to indicate you're dealing with an array.
Probably in an attempt to be more approachable for the .NET crowd, in type names F# uses []
as an alias for array
, so both forms are usable. It's rather unfortunate that this coincides with the empty list literal, but leaving that 'as is' was another constraint - one of early goals in F# design was to make it compatible with OCaml code, so that porting from that language to F# is as friction-less as possible.
Solution 2:[2]
If you want to implement some command-line utility I suggest using a wonderful library https://github.com/JordanMarr/FSharp.SystemCommandLine or https://github.com/cannorin/FSharp.CommandLine is also good.
But if you want to do that by hand, try
[<EntryPoint>]
let main (argv : string list) =
printfn "%A" argv
match argv with
| [] -> 42
| _ -> 43
or
[<EntryPoint>]
let main argv =
printfn "%A" argv
match argv |> List.ofArray with
| [] -> 42
| _ -> 43
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
Solution | Source |
---|---|
Solution 1 | |
Solution 2 | Andrii |