Values, types and printfn
What the page runs when you press Run, the five kinds of value the rest of the course is built from, and the format string that turns any of them into a line of output.
A file that runs from the top
The editor holds one file, main.fsx, and pressing Run hands it to an F# script engine. A script is read from the first line to the last, and each top-level line is carried out as it is reached: three printfn calls print three lines, and a file with none prints nothing at all.
There is no main function to define, no [<EntryPoint>], no namespace. What you see in the editor is the whole program, in the order it runs, which makes the output pane the most direct feedback a language can give you.
Every value has a type
42 is an int, 9.0 is a float, "text" is a string, true is a bool, and 'f' is a char. You rarely write those names yourself: the compiler works out the type of a value from how it is written and how it is used, and it complains at the first line where the two disagree rather than halfway through a run.
printfn takes a format string and one argument per placeholder. %d is a whole number, %s a string, %b a bool, %c a character, and %A prints any value at all. The placeholders are checked: %d given a float is a compile error, not a rounded number.
One division to watch from the start: 9 / 2 is 4, because both sides are whole numbers and the answer is the quotient. Write 9.0 / 2.0 and the slash is float division, so the answer is 4.5.
printfn answers unit, the type with one value written (). That is why a line that calls it cannot be used where a number is expected, and why a function whose last expression is a printfn has the type ... -> unit. The arrow is part of the signature, and it tells a caller that the function is for its effect rather than its answer.
The placeholders you will use most
printfn "a string: %s" "text"
printfn "a whole number: %d" 42
printfn "a float: %A" 4.5
printfn "two at once: %s = %d" "answer" 42Six lines, six kinds of value
Run it and read the six lines. Then change the arithmetic to something else and add a line of your own that prints a bool and a char.
A format string with two placeholders needs two arguments, and one with none needs none. When you are not sure which placeholder fits a value, %A always does: it prints the value the way you would write it.
A type is decided before the run
The compiler reads each value and works out its type from the way it is written: a bare number with no point is an int, a number with a point is a float, and text in double quotes is a string. Operators are overloaded, so + means integer addition here and floating-point addition there, and the operands decide which one is meant.
That is why 9 / 2 and 9.0 / 2.0 are different programs rather than different formatting. The first divides two whole numbers and keeps the quotient; the second divides two floats. There is no silent conversion between them, so the compiler asks you to make both sides agree instead of guessing which one you wanted.
printfn is checked the same way. Its format string is part of the call, and each placeholder fixes the type of the argument that fills it. A mismatch is a compile error with a line number, not a strange-looking line of output, which is the useful place for the mistake to appear.
Reading the output
The program prints in the order the lines run, one newline per printfn, so the output pane is a transcript rather than a summary. If a line is missing, the line above it usually stopped the script: a script halts at the first uncaught error, and the lines after it never run.
When you change a number, predict the new line before pressing Run. The gap between what you expected and what appeared is the useful part, and it is much easier to spot in six short lines than in a large program.
A script stops at the first uncaught exception, so a missing line is usually the symptom and the exception is the cause. The message names the line that raised it, not the line that printed last; read the two together.
Three mistakes appear first: writing "f" where a char is wanted, since a character takes single quotes; giving %d a float or %s a number instead of letting %A show it; and expecting two ints to divide into a fraction. The first two are compile errors; the third is legal and answers a whole number, which is why predicting the line is worthwhile.
Try these next
- Print one float with
%A,%.2fand%6.2f, and describe what each form changes. - Bind a price and a count, then print the total with one
printfnand two placeholders. - Swap the order of two arguments without swapping the placeholders, and read the compiler message.
A price tag with the right placeholders
Run it and match each line to its placeholder. Then change the quantity and the price, and add a line that prints the total with three decimal places.
Check what you learned
One question at a time. A wrong answer explains itself — take another go.
Part 1 of 5
What does the page run when you press Run?
