mail: vnovick@gmail.com
twitter: @VladimirNovick
github: vnovick
facebook: vnovickdev
Generics, Interfaces, Inheritance, Polymorphism, IoC, DI, MVC ...
Functions that can be assigned to variables, passed as parameters and returned from other functions
function getGreetingGenerator(greeting) {
return function(name) {
console.log(greeting + ", " + name);
}
}
var englishGreeting = getGreetingGenerator("Welcome");
englishGreeting("Vladimir Novick");
var sum = function add(a,b) {
return a + b
}
let sum = (a, b) => a + b
A function f takes an input x, and returns a single output f(x)
Side effect is when a function can change a program's state aside from it's returning value
var flag = true
function calc(){
// ....Calculations based on flag
return calculationResult
}
calc()
Pure Function
Function with Side effect
function calc(flagParam, ...args){
//...Calculations based on flagParam
return calculationResult
}
var flag = true
calc(flag, 1, 2.5, 3, 0.5)
RT is a formal way of defining Pure Function. If function always yields the same result on the same input it's called referential transparent
var jediCouncil = [
{ name: 'Yoda', origin: 'Dagobah', species: 'Unknown' },
{ name: 'Plo Koon', origin: 'Dorin', species: 'Kel Dor' },
{ name: 'Mace Windu', origin: 'Haruun Kal', species: 'Korunnai'},
{ name: 'Ki-Adi-Mundi', origin: 'Cerea', species: 'Cerean'},
{ name: 'Saesee tiin', origin: 'Iktotch', species: 'Iktotchi'},
{ name: 'yaddle', origin: 'Unknown', species: 'Unknown'},
{ name: 'even piell', origin: 'Haruun Kal', species: ''},
{ name: 'O. Rancisis', origin: 'Thisspias', species: 'Thisspiasian'},
{ name: 'Adi Gallia', origin: 'Tholothian', species: 'Tholothian'},
{ name: 'Yarael Poof', origin: '', species: 'Quermian'},
{ name: 'even piell', origin: 'Zabrak', species: 'Lannik'},
{ name: 'Obi-Wan Kenobi', origin: 'Stewjon', species: 'Human'},
]
// var humans = []
// for (var i = 0; i < jediCouncil.length; i++) {
// if (jediCouncil[i].species === 'Human') {
// humans.push(jediCouncil[i])
// }
// }
let isHuman = member =>
member.species === 'Human'
let humanCouncils = jediCouncil.filter(isHuman)
// find instead of filter returns only first element that matches
//[{"name":"Obi-Wan Kenobi","origin":"Stewjon","species":"Human"}]
// var text = [];
// for (var i=0; i < jediCouncil.length; i++ ) {
// text.push(jediCouncil[i].name +
// " is " +
// jediCouncil[i].species +
// " specie born on " +
// jediCouncil[i].origin)
// }
var text = jediCouncil.map( member =>
`${member.name} is ${member.species} specie born on ${member.origin}` )
console.log (text.join('\n'))
// Yoda is Unknown specie born on Dagobah
// Plo Koon is Kel Dor specie born on Dorin
// Mace Windu is Korunnai specie born on Haruun Kal
// Ki-Adi-Mundi is Cerean specie born on Cerea
// Saesee tiin is Iktotchi specie born on Iktotch
// yaddle is Unknown specie born on Unknown
// even piell is specie born on Haruun Kal
// O. Rancisis is Thisspiasian specie born on Thisspias
// Adi Gallia is Tholothian specie born on Tholothian
// Yarael Poof is Quermian specie born on
// even piell is Lannik specie born on Zabrak
// Obi-Wan Kenobi is Human specie born on Stewjon
let accumulator = {
jediNames: [],
planetsOfOrigin: []
}
let council = jediCouncil.reduce( (accumulator, item) => {
let { jediNames, planetsOfOrigin } = accumulator
return {
...accumulator,
...{
jediNames: [...jediNames, item.name],
planetsOfOrigin: [...planetsOfOrigin, item.origin]
}
}
},accumulator)
console.log(accumulator)
console.log(council)
// {"jediNames":[],"planetsOfOrigin":[]}
// {"jediNames":["Yoda","Plo Koon","Mace Windu","Ki-Adi-Mundi","Saesee tiin","yaddle","even piell","O. Rancisis","Adi Gallia","Yarael //Poof","even piell","Obi-Wan Kenobi"],"planetsOfOrigin":["Dagobah","Dorin","Haruun Kal","Cerea","Iktotch","Unknown","Haruun
// var counter = 0;
// var totalLength = jediCouncil.length;
// while(counter < totalLength) {
// var name = jediCouncil[counter].name
// console.log(counter++ + ")" + jediCouncil[counter].name);
// }
var printJedis = function(log, counter, jediCouncil) {
if (counter < jediCouncil.length) {
var name = jediCouncil[counter].name
log(counter + 1 + ")" + name);
return printJedis(log, counter + 1, jediCouncil);
}
};
printJedis(log, 0, jediCouncil);
// 1)Yoda
// 2)Plo Koon
// 3)Mace Windu
// 4)Ki-Adi-Mundi
// 5)Saesee tiin
// 6)yaddle
// 7)even piell
// 8)O. Rancisis
// 9)Adi Gallia
// 10)Yarael Poof
// 11)even piell
// 12)Obi-Wan Kenobi
let compose = (...fns) =>
fns.reduce(
(f, g) =>
(...args) =>
f(g(...args)));
(g∘ f )(x) = g(f(x)) for all x in X
f : X → Y and g : Y → Z can be composed to yield a function which maps x in X to g(f(x)) in Z
let isSpeciesUnknown = member =>
member.species === 'Unknown'
let getUnknownSpecies = (x) =>
x.filter(isSpeciesUnknown)
let printUnknownSpecies = (x) =>
x.map( member =>
`${member.name} is ${member.species} specie born on ${member.origin}` )
let getAndPrint = compose(printUnknownSpecies, getUnknownSpecies)
console.log (getAndPrint(jediCouncil))
console.log(
printUnknownSpecies(
getUnknownSpecies(jediCouncil)
)
)
// Result:
// ["Yoda is Unknown specie born on Dagobah","yaddle is Unknown specie born on Unknown"]
// ["Yoda is Unknown specie born on Dagobah","yaddle is Unknown specie born on Unknown"]
currying is the technique of translating the evaluation of a function that takes multiple arguments (or a tuple of arguments) into evaluating a sequence of functions, each with a single argument
becomes
Curry takes a function and transforms it to return chain of functions with one single argument for every function argument
f(a,b,c) transforms to f(a) -> f(b) -> f(c)
var printJediWelcome = (name, species, origin) => {
console.log( `Welcome, ${name}, the ${species} from ${origin}`)
}
var curriedJediWelcome = name => species => origin => {
console.log( `Welcome, ${name}, the ${species} from ${origin}`)
}
var genericJediWelcome = curriedJediWelcome('Jedi')
var onlyHumansWelcome = genericJediWelcome('human')
console.log(onlyHumansWelcome("Mars"))
//Welcome, Jedi, the human from Mars
var printJedisWelcome = (log, name, species, origin) => {
log( `Welcome, ${name}, the ${species} from ${origin}`)
}
let log = (...args) => { console.log(...args) }
curry(printJedisWelcome, log, "Jedi", "Human")("Earth")
curry(printJedisWelcome, log, "Jedi")("Human")("Earth")
curry(printJedisWelcome, log)("Jedi")("Human")("Earth")
curry(printJedisWelcome)(log)("Jedi")("Human")("Earth")
let log = (...args) => { console.log(...args) }
let fn1 = log.bind(null, 1, 2);
fn1(3, 4); // => 1, 2, 3, 4
let curry = (fn, ...args) => {
let _curry = (args) => {
return args.length < fn.length
? (..._args) => _curry([...args, ..._args])
: fn(...args);}
return _curry(args);
};
...But next time