Reputation: 8220
What is the difference between the following two statements in F#? Are they any advantages or disadvantages compared to each other (excluding the obvious syntax differences)?
I understand that WriteLine() is part of .NET, but do not understand what implications this might have.
The Sample Code:
printfn "This is an integer: %d" 5
System.Console.WriteLine("This is an integer: {0}" , 5)
Upvotes: 26
Views: 20054
Reputation: 48066
printfn
and its various cousins have several advantages:
printfn "%d" "bad type"
will not compile.%O
prints any object%A
printfn "%d, %d" 3
is a valid expression. This is particularly nifty since the compiler can check that you actually apply the right number of arguments when you later use this subexpression - unlike Console.WriteLine
which will happily accept too many or too few parameters.In practice, the most common partial application is likely to include just the format string; e.g.
let printParticle = printfn "Particle at (%d, %d), state %A, p = %f"
printParticle 2 3 //compile time warning about ignored value
printParticle 3 4 someState 0.4 //fine
printParticle 5 6 someState 0.4 0.7 //compile-time error
However, prior to F# 3.1, it's also slow. It's plenty fast enough to keep up with you the coder, but if you're using it in some form of serialization, it could turn into a bottleneck. The F# 3.1 release announcement (which is distributed as part of Visual Studio 2013) claims to improve the performance dramatically, though I have not verified this.
Personally, I usually use printfn for exploratory coding, and then I largely stick to %A
with the occasional other specifier thrown in. However, the .NET native string formatting is still useful in some cases for its detailed culture and formatting-related options. If you want maximum speed direct concatenation (or a StringBuilder
) will easily outperform both as this avoids interpreting the format string.
Upvotes: 42
Reputation: 19897
Aside from style, System.Console.WriteLine
has the advantage of being able to reuse parameters, i.e. System.Console.WriteLine("This is a integer twice: {0} {0}", 5)
Also, as noted here, you can do pretty printing of F# object using printfn
which you can't do with System.Console.WriteLine
and since it doesn't take a tuple, you can do partial application with it.
As noted by others, printfn
uses reflection and thus is significantly slower than PrintLine
, but also is typesafe.
Upvotes: 4
Reputation: 41290
Here are some pros and cons of printf
-like functions compared to Console.WriteLine
.
Pros:
printfn
functions are type-safe:
printfn "This is an integer: %i" 5 // works
printfn "This is an integer: %i" "5" // doesn't compile
It's easy to do partial application with printfn
, which is not the case with Console.WriteLine
due to excessive number of overloads:
[1; 2; 3] |> List.iter (printfn "%i; ")
printfn
support F# types better via %A
specifier.
Cons:
Aside from not being able to reuse parameters as @mydogisbox mentioned, printfn
-like functions are much slower than Console.WriteLine
(due to using reflection); you shouldn't use the former for logging purpose.
Upvotes: 8
Reputation: 546
The printfn function can be partially applicated.
let printDouble = printfn "%f"
printDouble 2.0
As the standard .NET functions take tuples as parameters in F#, you can't use partial application there.
A second advantage of printfn is, that the arguments are typed. So this won't compile:
let printDouble = printfn "%d"
printDouble 2.0
Upvotes: 4