Matching command line args
Asked Answered
V

2

13

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.

Vervain answered 1/3, 2017 at 21:11 Comment(0)
B
18

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.

Bechler answered 1/3, 2017 at 21:18 Comment(5)
Yes! That is confusing! Seems inconsistent, too, but thanks! your solution worksVervain
@Vervain do not forget to mark answer (just click to green tick) ;)Curium
@user1443098: Agreed. It is consistent in a sense, but probably not where you expect it to be. I've added some more background to the answer.Bechler
@Bechler could you also explain what [||] means and why it works?Cockle
@supertopi: that's the empty array literal, in the same way [] is an empty list. It's how you'd write an array with zero elements, just the opening and closing bracket are left.Bechler
C
0

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
Cytoplasm answered 27/4, 2022 at 11:46 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.