When working with any language, you will most likely need to format the text, and F # is no different.
Since F # is a .NET language, we can always use Console.WriteLine (..) and String.Format (..), where we can use any of the usual formatters that you used in your regular .NET code.
However, F # also supports a more syntax-like C method, which is available in the Core.Printf module. One function inside it can be used instead of using the Console.WriteLine (..) .NET class.
The equivalent F # function that should be used to write to standard output is printfn, which is actually the preferred method when working with text formatting in F #.
Why is printfn preferable to Console.WriteLine (..)?
There are several reasons why printfn is preferred; some of the main reasons are given below:
- Static type checking. This means that if we pass the int value where the string is expected, we will be warned about this
- Since printfn is a native F # function, it acts just like any other F # function.
Consider the following code snippets
// printfn "should be a decimal value %d" "cat" // printfn "should be a decimal value %d" 42 // , Console.WriteLine("should be a decimal value {0}" , "cat") // printfn "this only expected 1 arg of type decimal %d" 42 "dog" // , Console.WriteLine("this only expected 1 arg of type decimal {0}" , 42, "dog") // , printfn "this only expected 2 args of type decimal %d and string %s" 42 "dog"
If we now look at a screenshot of this code in the Visual Studio IDE, we really see that the lines that we expected to fail are clearly shown as erroneous:
How to use printfn?
Perhaps it's best to start by looking at some of the standard formatters available for working with values. The following MSDN table shows the standard operators available to you:
msdn.microsoft.com/en-us/library/ee370560.aspx
So what about creating great formatting besides the standard?
So, now we saw how to write formatted output to standard output (printfn did this), but what if we want to use the formatted line in other places? What if we want to associate a string value with a beautifully formatted string that we constructed using some of the formatting tools above, or even wanted to write to StringBuilder or TextWriter, does F # make this easy?
Well yes, actually it is, you will find many other useful features in the Core.Printf module. The full list at the time of this writing was as follows:
List bprintf Print to StringBuilder.
eprintf Prints formatted output to stderr.
eprintfn Prints formatted output to stderr by adding a new line.
failwithf Prints to a string buffer and throws an exception with the given result. Secondary printers must return strings.
fprintf Prints to text writter.
fprintfn Prints to text writter by adding a new line.
kbprintf Similar to bprintf, but it calls the specified function to generate the result. See kprintf.
kfprintf Similar to fprintf, but it calls the specified function to generate the result. See kprintf.
kprintf Like printf, but calls the specified function to generate the result. For example, they allow printing to be forcibly reset after all output has been entered into the channel, but not earlier.
kspintf Like sprintf, but calls the specified function to generate the result. See kprintf.
printf Prints formatted output to standard output.
printfn Prints formatted output to standard output by adding a new line.
sprintf Prints to a string using the internal string buffer, and returns the result as a string. Secondary printers must return strings.
I am not going to go through all this, but I will consider the most common:
bprintf
Prints to StringBuilder.
let builder = new StringBuilder(524288) Printf.bprintf builder "This will be a string line : %s\r\n" "cat" Printf.bprintf builder "This will be a bool line : %b\r\n" true Printf.bprintf builder "This will be a int line : %u\r\n" 42 Printf.bprintf builder "This will be a hex line : %X\r\n" 255 printfn "%s" (builder.ToString())
This will give this output in a F # console application
fprintf
Prints in a text writer.
use sw = new StreamWriter(@"c:\temp\fprintfFile.txt") fprintf sw "This is a string line %s\r\n" "cat" fprintf sw "This is a int line %i" 10 sw.Close()
This will cause the file to be created in temp
sprintf
let result = Printf.sprintf "This will return a formatted string : %s\r\n" "cat" printfn "%s" result