Armed with our knowledge about integers and reals and the useful ``pattern matching'' mechanism of Standard ML we are now able to implement a simple formula. A Reverend Zeller discovered a formula which calculates the day of the week for a given date. If d and m denote day and month and y and c denote year and century with each month decremented by two (January and February becoming November and December of the previous year) then the day of the week can be calculated according to the following formula.
(floor (2.61m - 0.2) + d + y + y ÷ 4 + c ÷ 4 - 2c) mod 7
This is simple to encode as a Standard ML function, zc, with a four-tuple as its argument if we know where to obtain the conversion functions in the Standard ML library. We will bind these to concise identifier names for ease of use. We choose the identifier floor for the real-to-integer function and real for the integer-to-real function. Note the potential for confusion because the name real is simultaneously the name of a function and the name of a type. Standard ML maintains different name spaces for these.
val floor = Real.floor val real = Real.fromInt val zc = fn (d, m, y, c) => (floor (2.61 * real (m) - 0.2) + d + y + y div 4 + c div 4 - 2 * c) mod 7;
Now we may use the pattern matching mechanism of Standard ML to perform the adjustment required for the formula to calculate the days correctly.
val zeller = fn (d, 1, y) => zc (d, 11, (y-1) mod 100, (y-1) div 100) | (d, 2, y) => zc (d, 12, (y-1) mod 100, (y-1) div 100) | (d, m, y) => zc (d, m - 2, y mod 100, y div 100);Although the zeller function correctly calculates days of the week its construction is somewhat untidy since the floor, real and zc functions have the same status as the zeller function although they were intended to be only sub-components. We require a language construct which will bundle the four functions together, making the inferior ones invisible. In Standard ML the local .. in .. end construct is used for this purpose.
local val floor = Real.floor val real = Real.fromInt val zc = fn (d, m, y, c) => (floor (2.61 * real (m) - 0.2) + d + y + y div 4 + c div 4 - 2 * c) mod 7 in val zeller = fn (d, 1, y) => zc (d, 11, (y-1) mod 100, (y-1) div 100) | (d, 2, y) => zc (d, 12, (y-1) mod 100, (y-1) div 100) | (d, m, y) => zc (d, m - 2, y mod 100, y div 100) end;Here we have three functions declared between the keyword local and the keyword in and one function defined between the keyword in and the keyword end. In general we could have a sequence of declarations in either place so a utility function could be shared between several others yet still not be made generally available. Either or both of the declaration sequences in local .. in .. end can be empty.