A list of small & fun functional programming exercises in JavaScript
A list of small & fun functional programming exercises in JavaScript.
Please see CONTRIBUTING.
npm install
to install the dependencies (need node.js for npm).filename
in test/tests.js
to the name of your solution file.Solutions
folder.At the bottom of your solution file, add
module.exports = {
identity,
addb,
subb,
mulb,
minb,
maxb,
add,
sub,
mul,
min,
max,
addRecurse,
mulRecurse,
minRecurse,
maxRecurse,
not,
acc,
accPartial,
accRecurse,
fill,
fillRecurse,
set,
identityf,
addf,
liftf,
pure,
curryb,
curry,
inc,
twiceUnary,
doubl,
square,
twice,
reverseb,
reverse,
composeuTwo,
composeu,
composeb,
composeTwo,
compose,
limitb,
limit,
genFrom,
genTo,
genFromTo,
elementGen,
element,
collect,
filter,
filterTail,
concatTwo,
concat,
concatTail,
gensymf,
gensymff,
fibonaccif,
counter,
revocableb,
revocable,
extract,
m,
addmTwo,
addm,
liftmbM,
liftmb,
liftm,
exp,
expn,
addg,
liftg,
arrayg,
continuizeu,
continuize,
vector,
exploitVector,
vectorSafe,
pubsub,
mapRecurse,
filterRecurse,
};
You can comment out any function names in the module.exports
that you haven't written yet, but a lot of the tests depend on previous functions to run properly so it's safer to write the functions in order.
Finally, npm run test
to run the tests.
any
Write a function identity
that
takes an argument and returns
that argument
number
Write a binary function addb
that takes two numbers and returns
their sum
number
Write a binary function subb
that takes two numbers and returns
their difference
number
Write a binary function mulb
that takes two numbers and returns
their product
number
Write a binary function minb
that takes two numbers and returns
the smaller one
number
Write a binary function maxb
that takes two numbers and returns
the larger one
number
Write a function add
that
is generalized for any
amount of arguments
number
Write a function sub
that
is generalized for any
amount of arguments
number
Write a function mul
that
is generalized for any
amount of arguments
number
Write a function min
that
is generalized for any
amount of arguments
number
Write a function max
that
is generalized for any
amount of arguments
number
Write a function addRecurse
that
is the generalized add
function
but uses recursion
number
Write a function mulRecurse
that
is the generalized mul
function
but uses recursion
number
Write a function minRecurse
that
is the generalized min
function
but uses recursion
number
Write a function maxRecurse
that
is the generalized max
function
but uses recursion
function
Write a function not
that
takes a function and returns
the negation of its result
function
Write a function acc
that
takes a function and an
initial value and returns
a function that runs the
initial function on each
argument, accumulating the
result
function
Write a function accPartial
that
takes in a function, a start index,
and an end index, and returns a
function that accumulates a subset
of its arguments by applying the
given function to all elements
between start and end.
function
Write a function accRecurse
that
does what acc
does but uses recursion
array
Write a function fill
that
takes a number and returns
an array with that many
numbers equal to the given
number
array
Write a function fillRecurse
that
does what fill
does but uses recursion
array
Write a function set
that
is given a list of arguments
and returns an array with
all duplicates removed
function
Write a function identityf
that takes an argument and
returns a function that
returns that argument
function
Write a function addf
that
adds from two invocations
function
Write a function liftf
that
takes a binary function, and
makes it callable with two
invocations
array
Write a pure function pure
that
is a wrapper arround the impure
function impure
function impure(x) { y++; z = x * y; }var y = 5, z;
impure(20); z; // 120
impure(25); z; // 175
function
Write a function curryb
that
takes a binary function and
an argument, and returns a
function that can take a
second argument
function
Write a function curry
that
is generalized for any amount
of arguments
number
Without writting any new functions,
show multiple ways to create the inc
function
function
Write a function twiceUnary
that takes a binary function
and returns a unary function
that passes its argument to
the binary function twice
number
Use the function twiceUnary
to
create the doubl
function
number
Use the function twiceUnary
to
create the square
function
any
Write a function twice
that
is generalized for any amount
of arguments
function
Write a function reverseb
that
reverses the arguments of a
binary function
function
Write a function reverse
that
is generalized for any amount
of arguments
function
Write a function composeuTwo
that
takes two unary functions and
returns a unary function that
calls them both
any
Write a function composeu
that
is generalized for any amount
of arguments
function
Write a function composeb
that
takes two binary functions and
returns a function that calls
them both
function
Write a function composeTwo
that
takes two functions and returns a
function that calls them both
function
Write a function compose
that
takes any amount of functions
and returns a function that takes
any amount of arguments and gives
them to the first function, then
that result to the second function
and so on
function
Write a function limitb
that allows a binary function
to be called a limited number
of times
function
Write a function limit
that
is generalized for any amount
of arguments
function
Write a function genFrom
that
produces a generator that will
produces a series of values
function
Write a function genTo
that
takes a generator and an end
limit, and returns a generator
that will produce numbers up
to that limit
function
Write a function genFromTo
that
produces a generator that will
produce values in a range
function
Write a function elementGen
that
takes an array and a generator
and returns a generator that will
produce elements from the array
function
Write a function element
that is a
modified elementGen
function so that
the generator argument is optional.
If a generator is not provided, then
each of the elements of the array
will be produced.
function
Write a function collect
that takes a
generator and an array and produces
a function that will collect the results
in the array
function
Write a function filter
that takes a
generator and a predicate and produces
a generator that produces only the
values approved by the predicate
function
Write a function filterTail
that uses
tail-recursion to perform the filtering
function
Write a function concatTwo
that takes
two generators and produces a generator
that combines the sequences
function
Write a function concat
that
is generalized for any amount
of arguments
function
Write a function concatTail
that uses
tail-recursion to perform the concating
function
Write a function gensymf
that
makes a function that generates
unique symbols
function
Write a function gensymff
that
takes a unary function and a
seed and returns a gensymf
function
Write a function fibonaccif
that
returns a generator that will
return the next fibonacci number
object
Write a function counter
that
returns an object containing
two functions that implement
an up/down counter, hiding
the counter
object
Write a function revocableb
that takes a binary function, and
returns an object containing an
invoke
function that can invoke a
function and a revoke
function
that disables the invoke
function
object
Write a function revocable
that
is generalized for any amount of
arguments
array
Write a function extract
that
takes an array of objects and an
object property name and converts
each object in the array by
extracting that property
object
Write a function m
that
takes a value and an
optional source string
and returns them in an
object
object
Write a function addmTwo
that
adds two m
objects and
returns an m
object
object
Write a function addm
that
is generalized for any amount of
arguments
object
Write a function liftmbM
that
takes a binary function and
a string and returns a function
that acts on m
objects
object
Write a function liftmb
that
is a modified function liftmbM
that can accept arguments that
are either numbers or m objects
object
Write a function liftm
that
is generalized for any amount of
arguments
any
Write a function exp
that
evaluates simple array
expressions
any
Write a function expn
that is a modified exp
that
can evaluate nested array
expressions
number
| undefined
Write a function addg
that
adds from many invocations,
until it sees an empty
invocation
function
Write a function liftg
that
will take a binary function
and apply it to many invocations
array
Write a function arrayg
that
will build an array from many
invocations
function
Write a function continuizeu
that takes a unary function
and returns a function that
takes a callback and an
argument
function
Write a function continuize
that takes a function and
returns a function that
takes a callback and an
argument
Make an array wrapper object
with methods get
, store
,
and append
, such that an
attacker cannot get access
to the private array
Let's assume your vector
implementation looks like
something like this:
vector = () => { let array = []; return { append: (v) => array.push(v), get: (i) => array[i], store: (i, v) => array[i] = v }; }
Can you spot any security concerns with
this approach? Mainly, can we get access
to the array
outside of vector
?
Note: the issue has nothing to do with
prototypes and we can assume that global
prototypes cannot be altered.
Hint: Think about using this
in a
method invocation. Can we override a
method of vector
?
How would you rewrite vector
to deal
with the issue from above?
Make a function pubsub
that
makes a publish/subscribe object.
It will reliably deliver all
publications to all subscribers
in the right order.
array
Make a function mapRecurse
that
performs a transformation for each
element of a given array, recursively
array
Make a function filterRecurse
that
takes in an array and a predicate
function and returns a new array by
filtering out all items using the
predicate, recursively.
any
Write a function
identitythat takes an argument and returns that argument
| Param | Type |
| ----- | ---------------- |
| x | any
|
Example
identity(3) // 3
number
Write a binary function
addbthat takes two numbers and returns their sum
| Param | Type |
| ----- | ------------------- |
| a | number
|
| b | number
|
Example
addb(3, 4) // 3 + 4 = 7
number
Write a binary function
subbthat takes two numbers and returns their difference
| Param | Type |
| ----- | ------------------- |
| a | number
|
| b | number
|
Example
subb(3, 4) // 3 - 4 = -1
number
Write a binary function
mulbthat takes two numbers and returns their product
| Param | Type |
| ----- | ------------------- |
| a | number
|
| b | number
|
Example
mulb(3, 4) // 3 * 4 = 12
number
Write a binary function
minbthat takes two numbers and returns the smaller one
| Param | Type |
| ----- | ------------------- |
| a | number
|
| b | number
|
Example
minb(3, 4) // 3
number
Write a binary function
maxbthat takes two numbers and returns the larger one
| Param | Type |
| ----- | ------------------- |
| a | number
|
| b | number
|
Example
maxb(3, 4) // 4
number
Write a function
addthat is generalized for any amount of arguments
| Param | Type |
| ------- | ------------------- |
| ...nums | number
|
Example
add(1, 2, 4) // 1 + 2 + 4 = 7
number
Write a function
subthat is generalized for any amount of arguments
| Param | Type |
| ------- | ------------------- |
| ...nums | number
|
Example
sub(1, 2, 4) // 1 - 2 - 4 = -5
number
Write a function
multhat is generalized for any amount of arguments
| Param | Type |
| ------- | ------------------- |
| ...nums | number
|
Example
mul(1, 2, 4) // 1 * 2 * 4 = 8
number
Write a function
minthat is generalized for any amount of arguments
| Param | Type |
| ------- | ------------------- |
| ...nums | number
|
Example
min(1, 2, 4) // 1
number
Write a function
maxthat is generalized for any amount of arguments
| Param | Type |
| ------- | ------------------- |
| ...nums | number
|
Example
max(1, 2, 4) // 4
number
Write a function
addRecursethat is the generalized
addfunction but uses recursion
| Param | Type |
| ------- | ------------------- |
| ...nums | number
|
Example
addRecurse(1, 2, 4) // 1 + 2 + 4 = 7
number
Write a function
mulRecursethat is the generalized
mulfunction but uses recursion
| Param | Type |
| ------- | ------------------- |
| ...nums | number
|
Example
mulRecurse(1, 2, 4) // 1 * 2 * 4 = 8
number
Write a function
minRecursethat is the generalized
minfunction but uses recursion
| Param | Type |
| ------- | ------------------- |
| ...nums | number
|
Example
minRecurse(1, 2, 4) // 1
number
Write a function
maxRecursethat is the generalized
maxfunction but uses recursion
| Param | Type |
| ------- | ------------------- |
| ...nums | number
|
Example
maxRecurse(1, 2, 4) // 4
function
Write a function
notthat takes a function and returns the negation of its result
| Param | Type |
| ----- | --------------------- |
| func | function
|
Example
const isOdd = (x) => x % 2 === 1 const isEven = not(isOdd) isEven(1) // false isEven(2) // true
function
Write a function
accthat takes a function and an initial value and returns a function that runs the initial function on each argument, accumulating the result
| Param | Type |
| ------- | --------------------- |
| func | function
|
| initial | any
|
Example
let add = acc(addb, 0) add(1, 2, 4) // 7let mul = acc(mulb, 1) mul(1, 2, 4) // 8
function
Write a function
accPartialthat takes in a function, a start index, and an end index, and returns a function that accumulates a subset of its arguments by applying the given function to all elements between start and end.
| Param | Type |
| ----- | --------------------- |
| func | function
|
| start | number
|
| end | number
|
Example
const addSecondToThird = accPartial(add, 1, 3) addSecondToThird(1, 2, 4, 8) // [ 1, 6, 8 ]
function
Write a function
accRecursethat does what
accdoes but uses recursion
| Param | Type |
| ------- | --------------------- |
| func | function
|
| initial | number
|
Example
let add = accRecurse(addb, 0) add(1, 2, 4) // 7let mul = accRecurse(mulb, 1) mul(1, 2, 4) // 8
array
Write a function
fillthat takes a number and returns an array with that many numbers equal to the given number
| Param | Type |
| ----- | ------------------- |
| num | number
|
Example
fill(3) // [ 3, 3, 3 ]
array
Write a function
fillRecursethat does what
filldoes but uses recursion
| Param | Type |
| ----- | ------------------- |
| num | number
|
Example
fillRecurse(3) // [ 3, 3, 3 ]
array
Write a function
setthat is given a list of arguments and returns an array with all duplicates removed
| Param | Type |
| ------- | ---------------- |
| ...args | any
|
Example
let oneAndTwo = set(1, 1, 1, 2, 2, 2) // [ 1, 2 ]
function
Write a function
identityfthat takes an argument and returns a function that returns that argument
| Param | Type |
| ----- | ---------------- |
| x | any
|
Example
let three = identityf(3) three() // 3
function
Write a function
addfthat adds from two invocations
| Param | Type |
| ----- | ------------------- |
| a | number
|
Example
addf(3)(4) // 7
function
Write a function
liftfthat takes a binary function, and makes it callable with two invocations
| Param | Type |
| ------ | --------------------- |
| binary | function
|
Example
let addf = liftf(addb) addf(3)(4) // 7liftf(mulb)(5)(6) // 30
array
Write a pure function
purethat is a wrapper arround the impure function
impure
function impure(x) { y++; z = x * y; } var y = 5, z; impure(20); z; // 120 impure(25); z; // 175
Returns: array
- an array containing
yand
z
| Param | Type |
| ----- | ------------------- |
| x | number
|
| y | number
|
Example
pure(20, 5) // [ 6, 120 ] pure(25, 6) // [ 7, 175 ]
function
Write a function
currybthat takes a binary function and an argument, and returns a function that can take a second argument
| Param | Type |
| ------ | --------------------- |
| binary | function
|
| a | any
|
Example
let add3 = curryb(addb, 3) add3(4) // 7curryb(mulb, 5)(6) // 30
function
Write a function
currythat is generalized for any amount of arguments
| Param | Type |
| -------- | --------------------- |
| func | function
|
| ...outer | any
|
Example
curry(add, 1, 2, 4)(4, 2, 1) = 1 + 2 + 4 + 4 + 2 + 1 = 14 curry(sub, 1, 2, 4)(4, 2, 1) = 1 - 2 - 4 - 4 - 2 - 1 = -12 curry(mul, 1, 2, 4)(4, 2, 1) = 1 * 2 * 4 * 4 * 2 * 1 = 64
number
Without writting any new functions, show multiple ways to create the
incfunction
| Param | Type |
| ----- | ------------------- |
| x | number
|
Example
inc(5) // 6 inc(inc(5)) // 7
function
Write a function
twiceUnarythat takes a binary function and returns a unary function that passes its argument to the binary function twice
| Param | Type |
| ------ | --------------------- |
| binary | function
|
Example
let doubl = twiceUnary(addb) doubl(11) // 22let square = twiceUnary(mulb) square(11) // 121
number
Use the function
twiceUnaryto create the
doublfunction
| Param | Type |
| ----- | ------------------- |
| x | number
|
Example
doubl(11) // 22
number
Use the function
twiceUnaryto create the
squarefunction
| Param | Type |
| ----- | ------------------- |
| x | number
|
Example
square(11) // 121
any
Write a function
twicethat is generalized for any amount of arguments
| Param | Type |
| ----- | --------------------- |
| x | function
|
Example
let doubleSum = twice(add) doubleSum(1, 2, 4) // 1 + 2 + 4 + 1 + 2 + 4 = 14
function
Write a function
reversebthat reverses the arguments of a binary function
| Param | Type |
| ------ | --------------------- |
| binary | function
|
Example
let bus = reverseb(subb) bus(3, 2) // -1
function
Write a function
reversethat is generalized for any amount of arguments
| Param | Type |
| ----- | --------------------- |
| func | function
|
Example
reverse(sub)(1, 2, 4) // 4 - 2 - 1 = 1
function
Write a function
composeuTwothat takes two unary functions and returns a unary function that calls them both
| Param | Type |
| ------ | --------------------- |
| unary1 | function
|
| unary2 | function
|
Example
composeuTwo(doubl, square)(5) // 100
any
Write a function
composeuthat is generalized for any amount of arguments
| Param | Type |
| -------- | --------------------- |
| ...funcs | function
|
Example
composeu(doubl, square, identity, curry(add, 1, 2))(5) // (5 + 5) * (5 + 5) + 1 + 2 = 103
function
Write a function
composebthat takes two binary functions and returns a function that calls them both
| Param | Type |
| ------- | --------------------- |
| binary1 | function
|
| binary2 | function
|
Example
composeb(addb, mulb)(2, 3, 7) // 35
function
Write a function
composeTwothat takes two functions and returns a function that calls them both
| Param | Type |
| ----- | --------------------- |
| func1 | function
|
| func2 | function
|
Example
composeTwo(add, square)(2, 3, 7) // (2 + 3 + 7)^2 = 144
function
Write a function
composethat takes any amount of functions and returns a function that takes any amount of arguments and gives them to the first function, then that result to the second function and so on
| Param | Type |
| -------- | --------------------- |
| ...funcs | function
|
Example
const f = compose(add, doubl, fill, max) f(0, 1, 2) // add(0, 1, 2) -> 3 // doubl(3) -> 6 // fill(6) -> [ 6, 6, 6, 6, 6, 6 ] // max([ 6, 6, 6, 6, 6, 6 ]) -> 6
function
Write a function
limitbthat allows a binary function to be called a limited number of times
| Param | Type |
| ------ | --------------------- |
| binary | function
|
| lmt | number
|
Example
let addLmtb = limitb(addb, 1) addLmtb(3, 4) // 7 addLmtb(3, 5) // undefined
function
Write a function
limitthat is generalized for any amount of arguments
| Param | Type |
| ----- | --------------------- |
| func | function
|
| lmt | number
|
Example
let addLmt = limit(add, 1) addLmt(1, 2, 4) // 7 addLmt(3, 5, 9, 2) // undefined
function
Write a function
genFromthat produces a generator that will produces a series of values
| Param | Type |
| ----- | ------------------- |
| x | number
|
Example
let index = genFrom(0)index.next().value // 0 index.next().value // 1 index.next().value // 2
function
Write a function
genTothat takes a generator and an end limit, and returns a generator that will produce numbers up to that limit
| Param | Type |
| ----- | --------------------- |
| gen | function
|
| lmt | number
|
Example
let index = genTo(genFrom(1), 3)index() // 1 index() // 2 index() // undefined
function
Write a function
genFromTothat produces a generator that will produce values in a range
| Param | Type |
| ----- | ------------------- |
| start | number
|
| end | number
|
Example
let index = genFromTo(0, 3) index() // 0 index() // 1 index() // 2 index() // undefined
function
Write a function
elementGenthat takes an array and a generator and returns a generator that will produce elements from the array
| Param | Type |
| ----- | --------------------- |
| array | array
|
| gen | function
|
Example
let ele = elementGen(['a', 'b', 'c', 'd'], genFromTo(1, 3))ele() // 'b' ele() // 'c' ele() // undefined
function
Write a function
elementthat is a modified
elementGenfunction so that the generator argument is optional. If a generator is not provided, then each of the elements of the array will be produced.
| Param | Type |
| ----- | --------------------- |
| array | array
|
| gen | function
|
Example
let ele = element(['a', 'b', 'c', 'd'])ele() // 'a' ele() // 'b' ele() // 'c' ele() // 'd' ele() // undefined
function
Write a function
collectthat takes a generator and an array and produces a function that will collect the results in the array
| Param | Type |
| ----- | --------------------- |
| gen | function
|
| array | array
|
Example
let array = [] let col = collect(genFromTo(0, 2), array)col() // 0 col() // 1 col() // undefined array // [0, 1]
function
Write a function
filterthat takes a generator and a predicate and produces a generator that produces only the values approved by the predicate
| Param | Type |
| --------- | --------------------- |
| gen | function
|
| predicate | function
|
Example
let fil = filter(genFromTo(0, 5), (val) => val % 3 === 0)fil() // 0 fil() // 3 fil() // undefined
function
Write a function
filterTailthat uses tail-recursion to perform the filtering
| Param | Type |
| --------- | --------------------- |
| gen | function
|
| predicate | function
|
Example
let third = (val) => val % 3 === 0 let fil = filterTail(genFromTo(0, 5), third)fil() // 0 fil() // 3 fil() // undefined
function
Write a function
concatTwothat takes two generators and produces a generator that combines the sequences
| Param | Type |
| ----- | --------------------- |
| gen1 | function
|
| gen2 | function
|
Example
let con = concatTwo(genFromTo(0, 3), genFromTo(0, 2)) con() // 0 con() // 1 con() // 2 con() // 0 con() // 1 con() // undefined
function
Write a function
concatthat is generalized for any amount of arguments
| Param | Type |
| ------- | --------------------- |
| ...gens | function
|
Example
let con = concat(genFromTo(0, 3), genFromTo(0, 2), genFromTo(5, 7)) con() // 0 con() // 1 con() // 2 con() // 0 con() // 1 col() // 5 col() // 6 con() // undefined
function
Write a function
concatTailthat uses tail-recursion to perform the concating
| Param | Type |
| ------- | --------------------- |
| ...gens | function
|
Example
let con = concatTail(genFromTo(0, 3), genFromTo(0, 2), genFromTo(5, 7)) con() // 0 con() // 1 con() // 2 con() // 0 con() // 1 col() // 5 col() // 6 con() // undefined
function
Write a function
gensymfthat makes a function that generates unique symbols
| Param | Type |
| ------ | ------------------- |
| symbol | string
|
Example
let genG = gensymf('G') let genH = gensymf('H')genG() // 'G1' genH() // 'H1' genG() // 'G2' genH() // 'H2'
function
Write a function
gensymffthat takes a unary function and a seed and returns a
gensymf
| Param | Type |
| ----- | --------------------- |
| unary | function
|
| seed | number
|
Example
let gensymf = gensymff(inc, 0) let genG = gensymf('G') let genH = gensymf('H')genG() // 'G1' genH() // 'H1' genG() // 'G2' genH() // 'H2'
function
Write a function
fibonaccifthat returns a generator that will return the next fibonacci number
| Param | Type |
| ------ | ------------------- |
| first | number
|
| second | number
|
Example
let fib = fibonaccif(0, 1) fib() // 0 fib() // 1 fib() // 1 fib() // 2 fib() // 3 fib() // 5 fib() // 8
object
Write a function
counterthat returns an object containing two functions that implement an up/down counter, hiding the counter
| Param | Type |
| ----- | ------------------- |
| i | number
|
Example
let obj = counter(10) let { up, down } = objup() // 11 down() // 10 down() // 9 up() // 10
object
Write a function
revocablebthat takes a binary function, and returns an object containing an
invokefunction that can invoke a function and a
revokefunction that disables the
invokefunction
| Param | Type |
| ------ | --------------------- |
| binary | function
|
Example
let rev = revocableb(addb)rev.invoke(3, 4) // 7 rev.revoke() rev.invoke(5, 7) // undefined
object
Write a function
revocablethat is generalized for any amount of arguments
| Param | Type |
| ----- | --------------------- |
| func | function
|
Example
let rev = revocable(add)rev.invoke(3, 4) // 7 rev.revoke() rev.invoke(5, 7) // undefined
array
Write a function
extractthat takes an array of objects and an object property name and converts each object in the array by extracting that property
| Param | Type |
| ----- | ------------------- |
| array | array
|
| prop | string
|
Example
let people = [{ name: 'john' }, { name: 'bob' }] let names = extract(people, 'name') // ['john', 'bob']
object
Write a function
mthat takes a value and an optional source string and returns them in an object
| Param | Type |
| ------ | ---------------- |
| value | any
|
| source | any
|
Example
JSON.stringify(m(1)) // '{"value":1,"source":"1"}'JSON.stringify(m(Math.PI, 'pi')) // '{"value":3.14159...,"source":"pi"}'
object
Write a function
addmTwothat adds two
mobjects and returns an
mobject
| Param | Type |
| ----- | --------------------- |
| m1 | function
|
| m2 | function
|
Example
JSON.stringify(addmTwo(m(3), m(4))) // '{"value":7,"source":"(3+4)"}'JSON.stringify(addmTwo(m(1), m(Math.PI, 'pi'))) // '{"value":4.14159...,"source":"(1+pi)"}'
object
Write a function
addmthat is generalized for any amount of arguments
| Param | Type |
| ----- | --------------------- |
| ...ms | function
|
Example
JSON.stringify(addm(m(1), m(2), m(4))) // '{"value":7,"source":"(1+2+4)"}'
object
Write a function
liftmbMthat takes a binary function and a string and returns a function that acts on
mobjects
| Param | Type |
| ------ | --------------------- |
| binary | function
|
| op | string
|
Example
let addmb = liftmbM(addb, '+')JSON.stringify(addmb(m(3), m(4))) // '{"value":7,"source":"(3+4)"}'
JSON.stringify(liftmbM(mul, '')(m(3), m(4))) // '{"value":12,"source":"(34)"}'
object
Write a function
liftmbthat is a modified function
liftmbMthat can accept arguments that are either numbers or m objects
| Param | Type |
| ------ | --------------------- |
| binary | function
|
| op | string
|
Example
let addmb = liftmb(addb, '+')JSON.stringify(addmb(3, 4)) // '{"value":7,"source":"(3+4)"}'
object
Write a function
liftmthat is generalized for any amount of arguments
| Param | Type |
| ----- | --------------------- |
| func | function
|
| op | string
|
Example
let addm = liftm(add, '+')JSON.stringify(addm(m(3), m(4))) // '{"value":7,"source":"(3+4)"}'
JSON.stringify(liftm(mul, '')(m(3), m(4))) // '{"value":12,"source":"(34)"}'
any
Write a function
expthat evaluates simple array expressions
| Param | Type |
| ----- | ---------------- |
| value | any
|
Example
let sae = [mul, 1, 2, 4] exp(sae) // 1 * 2 * 4 = 8 exp(42) // 42
any
Write a function
expnthat is a modified
expthat can evaluate nested array expressions
| Param | Type |
| ----- | ---------------- |
| value | any
|
Example
let nae = [Math.sqrt, [add, [square, 3], [square, 4]]]expn(nae) // sqrt(((33)+(44))) === 5
number
| undefined
Write a function
addgthat adds from many invocations, until it sees an empty invocation
| Param | Type |
| ----- | ------------------- |
| value | number
|
Example
addg() // undefined addg(2)() // 2 addg(2)(7)() // 9 addg(3)(0)(4)() // 7 addg(1)(2)(4)(8)() // 15
function
Write a function
liftgthat will take a binary function and apply it to many invocations
| Param | Type |
| ------ | --------------------- |
| binary | function
|
Example
liftg(mulb)() // undefined liftg(mulb)(3)() // 3 liftg(mulb)(3)(0)(4)() // 0 liftg(mulb)(1)(2)(4)(8)() // 64
array
Write a function
arraygthat will build an array from many invocations
| Param | Type |
| ----- | ---------------- |
| value | any
|
Example
arrayg() // [] arrayg(3)() // [3] arrayg(3)(4)(5)() // [3, 4, 5]
function
Write a function
continuizeuthat takes a unary function and returns a function that takes a callback and an argument
| Param | Type |
| ----- | --------------------- |
| unary | function
|
Example
sqrtc = continuizeu(Math.sqrt) sqrtc(console.log, 81) // logs '9'
function
Write a function
continuizethat takes a function and returns a function that takes a callback and an argument
| Param | Type |
| ----- | --------------------- |
| any | function
|
Example
mullc = continuize(Math.mul) mulc(console.log, 81, 4, 2) // logs '648'
Make an array wrapper object with methods
get,
store, and
append, such that an attacker cannot get access to the private array
Example
let v = vector() v.append(7) v.store(1, 8) v.get(0) // 7 v.get(1) // 8
Let's assume your
vectorimplementation looks like something like this:
vector = () => { let array = []; return { append: (v) => array.push(v), get: (i) => array[i], store: (i, v) => array[i] = v }; }
Can you spot any security concerns with this approach? Mainly, can we get access to the
arrayoutside of
vector? Note: the issue has nothing to do with prototypes and we can assume that global prototypes cannot be altered. Hint: Think about using
thisin a method invocation. Can we override a method of
vector?
Example
let v = vector() v.append(1) v.append(2) let internalData = exploitVector(v) // [1, 2]
How would you rewrite
vectorto deal with the issue from above?
Example
let v = vectorSafe() v.append(1) v.append(2) let internalData = exploitVector(v) // undefined
Make a function
pubsubthat makes a publish/subscribe object. It will reliably deliver all publications to all subscribers in the right order.
Example
let ps = pubsub() ps.subscribe(log) ps.publish('It works!') // log('It works!')
array
Make a function
mapRecursethat performs a transformation for each element of a given array, recursively
| Param | Type |
| --------- | --------------------- |
| array | array
|
| predicate | function
|
Example
mapRecurse([1, 2, 3, 4], (x) => x * 2) // [ 2, 4, 6, 8 ]
array
Make a function
filterRecursethat takes in an array and a predicate function and returns a new array by filtering out all items using the predicate, recursively.
| Param | Type |
| --------- | --------------------- |
| array | array
|
| predicate | function
|
Example
filterRecurse([1, 2, 3, 4], (x) => x % 2 === 0) // [ 2, 4 ]