4,461
edits
Line 1,180: | Line 1,180: | ||
// object[first] = "Deacon" | // object[first] = "Deacon" | ||
</source> | |||
=== Composition === | |||
chaining | |||
<source lang="js"> | |||
const template = "hh:mm:ss tt"; | |||
const clockTime = template | |||
.replace("hh", "03") | |||
.replace("mm", "33") | |||
.replace("ss", "33") | |||
.replace("tt", "PM"); | |||
console.log(clockTime); | |||
// "03:33:33 PM" | |||
</source> | |||
<code>both</code> function pipes a value through two separate functions. | |||
<source lang="js"> | |||
const both = date => appendAMPM(civilianHours(date)); | |||
// but hard to read, so better approach is to use higher order function | |||
const compose = (...fns) => arg => | |||
fns.reduce((composed, f) => f(composed), arg); | |||
const both = compose( | |||
civilianHours, | |||
appendAMPM | |||
); | |||
both(new Date()); | |||
</source> | |||
== Putting it all together == | |||
ticking time | |||
<source lang="js"> | |||
// Log Clock Time every Second | |||
setInterval(logClockTime, 1000); | |||
function logClockTime() { | |||
// Get Time string as civilian time | |||
let time = getClockTime(); | |||
// Clear the Console and log the time | |||
console.clear(); | |||
console.log(time); | |||
} | |||
function getClockTime() { | |||
// Get the Current Time | |||
let date = new Date(); | |||
let time = ""; | |||
// Serialize clock time | |||
let time = { | |||
hours: date.getHours(), | |||
minutes: date.getMinutes(), | |||
seconds: date.getSeconds(), | |||
ampm: "AM" | |||
}; | |||
// Convert to civilian time | |||
if (time.hours == 12) { | |||
time.ampm = "PM"; | |||
} else if (time.hours > 12) { | |||
time.ampm = "PM"; | |||
time.hours -= 12; | |||
} | |||
// Prepend a 0 on the hours to make double digits | |||
if (time.hours < 10) { | |||
time.hours = "0" + time.hours; | |||
} | |||
// prepend a 0 on the minutes to make double digits | |||
if (time.minutes < 10) { | |||
time.minutes = "0" + time.minutes; | |||
} | |||
// prepend a 0 on the seconds to make double digits | |||
if (time.seconds < 10) { | |||
time.seconds = "0" + time.seconds; | |||
} | |||
// Format the clock time as a string "hh:mm:ss tt" | |||
return time.hours + ":" + time.minutes + ":" + time.seconds + " " + time.ampm; | |||
} | |||
</source> | |||
REFACTORING using what we learned | |||
in functional programs, use functions over values wherever possible; invoke the function to obtain the value when needed | |||
<source lang="js"> | |||
const oneSecond = () => 1000; | |||
const getCurrentTime = () => new Date(); | |||
const clear = () => console.clear(); | |||
const log = message => console.log(message); | |||
</source> | |||
three functions will be used to mutate the clock | |||
# serializeClockTime - take a date object and returns a object for clock time that contains hours minutes, and seconds. | |||
# civilianHours - takes the clock time object and returns an object where hours are converted to civilian time (1300 becomes 1:00) | |||
# appendAMPM - take the clock time object and appends time of day, AM or PM, to that object. | |||
<source lang="js"> | |||
const serializeClockTime = date => ({ | |||
hours: date.getHours(), | |||
minutes: date.getMinutes(), | |||
seconds: date.getSeconds() | |||
}); | |||
const civilianHours = clockTime => ({ | |||
...clockTime, | |||
hours: clockTime.hours > 12 ? clockTime.hours - 12 : clockTime.hours | |||
}); | |||
const appendAMPM = clockTime => ({ | |||
...clockTime, | |||
ampm: clockTime.hours >= 12 ? "PM" : "AM" | |||
}); | |||
</source> | |||
higher order functions needed | |||
# display - takes a target function and returns a function that will send a time to the target. In this eample the target will be console.log | |||
# formatClock - takes a template string and uses it to return clock time formatted based upon the criteria from the string. | |||
# prependZero - | |||
<source lang="js"> | |||
const display = target => time => target(time); | |||
const formatClock = format => time => | |||
format | |||
.replace("hh", time.hours) | |||
.replace("mm", time.minutes) | |||
.replace("ss", time.seconds) | |||
.replace("tt", time.ampm); | |||
const prependZero = key => clockTime => ({ | |||
...clockTime, | |||
[key]: clockTime[key] < 10 ? "0" + clockTime[key] : clockTime[key] | |||
}); | |||
</source> | |||
compose | |||
<source lang="js"> | |||
const convertToCivilianTime = clockTime => | |||
compose( | |||
appendAMPM, | |||
civilianHours | |||
)(clockTime); | |||
const doubleDigits = civilianTime => | |||
compose( | |||
prependZero("hours"), | |||
prependZero("minutes"), | |||
prependZero("seconds") | |||
)(civilianTime); | |||
const startTicking = () => | |||
setInterval( | |||
compose( | |||
clear, | |||
getCurrentTime, | |||
serializeClockTime, | |||
convertToCivilianTime, | |||
doubleDigits, | |||
formatClock("hh:mm:ss tt"), | |||
display(log) | |||
), | |||
oneSecond() | |||
); | |||
startTicking(); | |||
</source> | </source> |