functionsortStudentsByID() { // Don't modify this function students.sort(functionbyID(s1,s2){ return s1.id - s2.id; }); return students; }
// *************************************
// Wrappers functiongetStudentsByName(students) { students = students.slice() // students belongs to function scope returnsortStudentsByName()
functionsortStudentsByName() { // Don't modify this function students.sort(functionbyName(s1,s2){ if (s1.name < s2.name) return -1; elseif (s1.name > s2.name) return1; elsereturn0; }); return students; } }
// Adapters // modify/move this function functiongetStudentsByID(curStudents) { var originStudents = students.slice() students = curStudents.slice() var newStudents = sortStudentsByID() students = originStudents return newStudents; }
Tacit programming (point-free programming) is a programming paradigm
in which a function definition does not include information regarding
its arguments, using combinators and function composition [...] instead
of variables.
function (fn2, fn1) { returnfunctioncomposed(v){ returnfn2(fn1(v)) } }
Closure
Closure is not necessarily functional pure. But closure could be used
in functional theory.
1 2 3 4 5 6 7 8 9 10 11 12 13 14
// this is a unpure function functionmakeCounter(){ var counter = 0; returnfunctionincrement(){ return ++counter; } }
// this is functional pure functionaddAnother(z) { returnfunctionaddTwo(x,y){ return x + y + z } }
if we are using closure in functional programming, we have to make
sure that we are closing over non-changing, non-mutating variables.
1 2 3 4 5 6 7 8 9
// here each time, next function close over a different variable that did not change its state. functionstrBuilder(str){ returnfunctionnext(v) { if(typeofv=="string") { returnstrBuilder(str+v) } returnstr; } }
Memoization
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
functionrepeater(count) { var str returnfunctionallTheAs() { if (str == undefined) { str = "".padStart(count,'A') } return str; } }
A function call is pure if it has referential transparency.
Referential Transparency means a function call can be replaced with its
return value and not affect any of the rest of the program
Partial Application &
Currying
Both are specialization techniques. Currying is a special form of
partial application. Partial Application presets some arguments now,
receives the rest on the next call Currying doesn't preset any
arguments, received each argument one at a time.
// make sure this function is pure functionpickNumber(num,nums) { if (!nums.includes(num)) { nums = [num,...nums]; nums.sort(functionasc(a,b){ return a - b; }); } return nums; }
single function call, nothing else in the expression that needs to
be computed afterwards
1 2 3 4 5 6 7
function countVowels(count, str) { count += (isVowel(str[0]? 1: 0)) if (str.length <= 1) returncount; return countVowels(count, str.slice(1)) }
var countVowels = curry(2, countVowels)(0)
Trampolines
With the regular recursion function, we literally stack up the work.
In the trampoline, we never stack up the work, we do some work and
return work back to this helper(iterative).
we could write a tail call for function then we could wrap the tail
call function into a function to make it trampolinable function.
1 2 3 4 5 6 7 8 9
functiontrampoline(fn) { returnfunctiontrampilined(...args){ var result = fn(...args); while(typeof result == "function"){ result = result() } return result; } }