I was playing around with F# (Visual Studio 2010 beta 1), and I wrote a little console script that asked the user to input 2 numbers and an operator and then executed it.
It works fine, apart from a tiny, but annoying thing: sometimes my printfn instructions are ignored. I placed breakpoints in the code to see that’s indeed the case.
The code snippet:
let convert (source : string) =
try System.Int32.Parse(source)
with :? System.FormatException ->
printfn "'%s' is not a number!" source;
waitForExitKey();
exit 1
let read =
printfn "Please enter a number.";
System.Console.ReadLine
let num1 : int = read() |> convert // the printfn in the read function is run...
let num2 : int = read() |> convert // ... but here is ignored
This is not the complete source of course, but I think that’ll be enough. If you need the complete source just let me know.
So my question is pretty simple: what causes this issue with printfn? Am I doing something wrong?
Thanks in advance,
ShdNx
This page has a partial explanation of what’s going on, but the short and sweet version is that F# will execute any value on declaration if it doesn’t take parameters.
Since
readdoesn’t take any parameters, its executed immediately on declaration and binds the return value of the function to the identifierread.Incidentally, your return value happens to be a function with the type
(unit -> string). This results because F# automatically curries functions if they aren’t passed all of their parameters.ReadLineexpects one unit parameter, but since it isn’t passed on, you actually bindreadto theReadLinefunction itself.The solution is as follows:
Since
readtakes one parameter, its re-evaluated each time its called. Additionally, we’re passing a parameter toReadLine, otherwise we’ll just return theReadLinefunction as a value.