I'm learning F# and finding I'm writing things that work but which I don't entirely understand. Here's an example
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
The methods getCredentials, home, mentions, messages, showHelp, and clearAllSettings are all simple functions and do what you expect. (Yes, it's a twitter client, isn't that the new 'Hello World' demo?)
The line:
[fun() -> getCredentials(); home 20; mentions 20; messages 20]
works like I want. It calls getCredentials, then home, then mentions, then messages
From my perspective, the semicolon is acting like a statement separator. I haven't seen this described before. Is that what is going on here?
Is there a more idiomatic way of writing this (in other words, would a seasoned F# programmer roll on the floor laughing when he/she saw this)?
Further information: My original intent was to have a list of actions and then add actions as I discover options. In C# I would typically do this with List< Action >(). The semicolon thing surprised me because originally I tried to write it like:
[getCredentials; home 20; mentions 20; messages 20]
But the compiler didn't like it.
When you write:
[fun() -> getCredentials(); home 20; mentions 20; messages 20]
the compiler creates a list with only one element which is a function of type unit -> unit
. S1 ; S2
is sequence composition when S1 has type of unit
, and S1 and S2 are executed in order and S2's result is returned. Therefore, three functions home
, mentions
and messages
actually have the signature int -> unit
.
If you want to create a list of 4 different functions, it should be:
[ getCredentials; // ; is optional
fun () -> home 20;
fun () -> mentions 20;
fun () -> messages 20 ]
These functions are separated by whitespace to avoid confusion of using ; as list delimiter and sequence composition.
Since your example has all lists with only one elements, it could be simplified a lot:
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
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With