In the process of learning F#, I wrote this code that reads lines of input from the console and stores them in a list.
As far as I can tell the code works correctly, but since I'm new to functional programming, I'm not sure if it is written as well as it could have been.
- Should I have read characters iteratively instead of recursively?
- Is there a better alternative to using a
StringBuilder
object? - Does my code follow proper functional style?
open System
/// Appends a character to the string builder and returns the new builder.
/// Characters 10 and 13 (newline and carriage return) are ignored.
/// Returns the updated StringBuilder.
let appendChar char (builder : Text.StringBuilder) =
match char with
| 10 | 13 -> builder
| n ->
let c = Convert.ToChar(n)
builder.Append(c)
/// Finishes building a string by clearing the StringBuilder
/// and appending the string to the end of the list of strings.
/// Empty strings are ignored.
/// Returns a tuple containing the lines and the new StringBuilder.
let finishString lines (builder : Text.StringBuilder) =
let s = builder.ToString()
let l = builder.Length
let newBuilder = builder.Clear()
match l with
| 0 -> (lines, newBuilder)
| _ -> (lines @ [s], newBuilder)
/// Handles a character by appending it to the builder and taking an appropriate action.
/// If char is a newline, finish the string.
/// Returns a tuple containing lines and the new builder.
let handleChar char lines builder =
let newBuilder = appendChar char builder
match char with
| 10 -> finishString lines newBuilder
| c -> (lines, newBuilder)
/// Gets all the lines from standard input until end of input (Ctrl-Z).
/// Empty lines are ignored.
/// Returns a list of strings read.
let rec getLines lines builder =
match Console.Read() with
| -1 -> lines
| c ->
let tuple = handleChar c lines builder
let newLines = fst tuple
let newbuilder = snd tuple
getLines newLines newbuilder
[<EntryPoint>]
let main argv =
Text.StringBuilder()
|> getLines []
|> ... and so on