Functional programming is becoming more and more popular. It's quite obvious that there are many benefits on using FP elements on server side. How does it look like in JavaScript world? I will focus on functional concepts that can improve our every day work. I won't talk about monads, functors and other mathematical concepts. We'll see how functional style can improve our codebase, make it more readable or simplify complex problems. Samples will be presented in JavaScript, but concepts are general for every programming language.
9. In programming language design, a first-class citizen (…) is an
entity which supports all the operations generally available to
other entities. These operations typically include being passed
as an argument, returned from a function, and assigned to a
variable
10. let languages = ['JavaScript', 'Scala', 'Go']
...
...
...
...
let divs = []
for(let i = 0; i < languages.length; i++) {
divs.push(`<div>${langs[i]}</div>`)
}
11. let languages = ['JavaScript', 'Scala', 'Go']
languages.push('Java')
languages.push('Ruby')
languages.splice(0, 3)
let divs = []
for(let i = 0; i < languages.length; i++) {
divs.push(`<div>${languages[i]}</div>`)
}
12. const languages = Immutable.List.of(
‘JavaScript',
‘Scala',
‘Go'
)
...
...
let divs = []
for(let i = 0; i < languages.length; i++)
{
divs.push(`<div>${languages[i]}</div>`)
}
13. • always evaluates to same result for the same
input
• evaluation does not cause any semantically
observable side effects
Pure function
14. let user = {...}
function createMessage(text) {
const message = Db.save(text)
return message
}
function sendMessage(text) {
const message = createMessage(text)
const messageId = MessageService.send(message, user)
return messageId
}
IMPURE
19. The problem with object-oriented languages is they’ve got all
this implicit environment that they carry around with them. You
wanted a banana but what you got was a gorilla holding the
banana... and the entire jungle
Joe Armstrong, Erlang creator
46. const find = (list, predicate) => {
for (let i = 0; i < list.length; ++i) {
const item = list[i]
if (predicate(item)) {
return item
}
}
return null
}
47. const render = (text) => (`<div>That one is AWESOME ${text}!!!</div>`)
const langs = ['JS', 'Haskell', 'Scala']
const js = find(langs, l => return l.length === 2)
if (js !== null) {
return '<div>hmm</div>'
} else {
render(js)
}
//OR
const render = (text) => {
if(text == null) {
return '<div>hmm</div>'
} else {
return `<div>That one is AWESOME ${text}!!!</div>`
}
}
const js = find(langs, l => return l === 'JS')
render(js)
48. const find = (list, predicate) => {
for (let i = 0; i < list.length; ++i) {
const item = list[i]
if (predicate(item)) {
return item
}
}
return null
}
const find = (list, predicate) => {
for (let i = 0; i < list.length; ++i) {
const item = list[i]
if (predicate(item)) {
return Maybe.Just(item)
}
}
return Maybe.Nothing()
}
and I say MAYBE
49. const render = (text) => (`<div>That one is AWESOME ${text}!!!</div>`)
const langs = ['JS', 'Haskell', 'Scala']
const best = find(langs, l => return l === 'JS')
best
.map(render)
.getOrElse('<div>hmm</div>)
55. function createTimeslots(trip) {
const slots = _.reduce(trip.days, (acc, d) => {
let [startHour, startMinutes] = _.map(d.startHour.split(':'), i =>
parseInt(i, 10))
startMinutes = normalizeStartMinutes(startMinutes)
const start = ...
const [endHour, endMinutes] = _.map(d.endHour.split(':'), i =>
parseInt(i, 10))
const end = ...
/// GIVE ME MORE
return acc
}, [])
return slots
}
56. function createTimeslots(trip) {
///GIVE ME MORE
}
function createTimeslotsFromTrips(trips) {
return map(trips, createTimeslots).flatten()
}
function createTimeslotsFromTrips(trips) {
return flatMap(trips, createTimeslots)
}
function createTimeslotsFromTrips(trips) {
return flatMap(createTimeslots, trips)
}
function createTimeslotsFromTrips(trips) {
return flatMap(createTimeslots)(trips)
}