Reading — step 1 of 7
Learn
F# uses .NET's I/O primitives. The printfn family handles formatted output; System.Console.ReadLine() reads input. The Microsoft F# docs cover this thoroughly.
printfn — formatted output
printfn "hello" // hello
printfn "name: %s, age: %d" "Ada" 36 // name: Ada, age: 36
printfn "%.2f" 3.14159 // 3.14
printfn "%A" [1; 2; 3] // [1; 2; 3] — generic pretty-print
printfn "%O" obj // calls .ToString()
Format specifiers:
%s— string%d— int%f— float%b— bool%c— char%A— generic pretty (works on any type)%O— uses .ToString()
TYPE-CHECKED format strings
Like OCaml, format strings are checked at compile time:
printfn "%d" "hello"
// Compile error: This expression was expected to have type int but has type string
Far safer than C's printf. Mismatches don't compile.
sprintf — to a string
let greeting = sprintf "Hello, %s, age %d" "Ada" 36
Returns a string. Same format syntax as printfn.
printf vs printfn
printfn— adds a newlineprintf— no newline
For output that's eventually displayed, prefer printfn.
Reading input
let line = System.Console.ReadLine()
let n = int line
let f = float line
System.Console.ReadLine() returns the next line as a string, or null at end-of-input. F#'s int and float are conversion functions — not just types.
Reading multiple lines
let readN n =
[for _ in 1..n -> System.Console.ReadLine()]
let n = int (System.Console.ReadLine())
let lines = readN n
List comprehension [for x in xs -> expr] is F#'s way of building lists by iteration.
Reading until EOF
let readAllLines () =
let lines = ResizeArray<string>()
let mutable line = System.Console.ReadLine()
while line <> null do
lines.Add(line)
line <- System.Console.ReadLine()
List.ofSeq lines
null is the EOF signal in .NET I/O. F# generally avoids null but here it's necessary for interop.
Or more functionally:
let readAllLines () =
let rec loop acc =
match System.Console.ReadLine() with
| null -> List.rev acc
| line -> loop (line :: acc)
loop []
Standard streams
printfn "to stdout"
eprintfn "to stderr" // ePrintfn — error stream
System.Console.Out.WriteLine("to stdout")
System.Console.Error.WriteLine("to stderr")
eprintfn is the stderr equivalent.
File I/O
open System.IO
let content = File.ReadAllText("data.txt")
let lines = File.ReadAllLines("data.txt")
File.WriteAllText("out.txt", "hello world")
File.WriteAllLines("out.txt", [|"line1"; "line2"|])
For large files, use streams:
use reader = new StreamReader("big.log")
while not reader.EndOfStream do
let line = reader.ReadLine()
process line
The use keyword auto-closes the resource (like using in C#).
Common mistakes
- Forgetting
nullfor EOF — System.Console.ReadLine returns null at end-of-input, not raising. F# doesn't have automatic null safety; check explicitly. - Using
intconfused with the type —int xis a CONVERSION;intas a type means System.Int32. Context distinguishes. printfnvsConsole.WriteLine— both work. printfn has type-checked format strings; Console.WriteLine is plain. Use printfn for formatted output.- Forgetting
eprintfnfor errors — output to stderr matters in CLI tools. - Buffered output not flushing —
Console.Out.Flush()if needed; print*n usually handles this.
Discussion
Ask a question, share an insight, or help someone who’s stuck.
Sign in to post a comment or reply.
Loading…