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). If you don’t have node please visit the Node JS website to download. It is recommended to download the LTS version.filename
in test/tests.js
to the name of your solution file (optional).Solutions
folder.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,
};
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.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 arguments
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:
let 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 identity
that
takes an argument and returns
that argument
Param | Type |
---|---|
x | any |
Example
identity(3) // 3
number
Write a binary function addb
that 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 subb
that 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 mulb
that 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 minb
that takes two numbers and returns
the smaller one
Param | Type |
---|---|
a | number |
b | number |
Example
minb(3, 4) // 3
number
Write a binary function maxb
that takes two numbers and returns
the larger one
Param | Type |
---|---|
a | number |
b | number |
Example
maxb(3, 4) // 4
number
Write a function add
that
is generalized for any
amount of arguments
Param | Type |
---|---|
…nums | number |
Example
add(1, 2, 4) // 1 + 2 + 4 = 7
number
Write a function sub
that
is generalized for any
amount of arguments
Param | Type |
---|---|
…nums | number |
Example
sub(1, 2, 4) // 1 - 2 - 4 = -5
number
Write a function mul
that
is generalized for any
amount of arguments
Param | Type |
---|---|
…nums | number |
Example
mul(1, 2, 4) // 1 * 2 * 4 = 8
number
Write a function min
that
is generalized for any
amount of arguments
Param | Type |
---|---|
…nums | number |
Example
min(1, 2, 4) // 1
number
Write a function max
that
is generalized for any
amount of arguments
Param | Type |
---|---|
…nums | number |
Example
max(1, 2, 4) // 4
number
Write a function addRecurse
that
is the generalized add
function
but uses recursion
Param | Type |
---|---|
…nums | number |
Example
addRecurse(1, 2, 4) // 1 + 2 + 4 = 7
number
Write a function mulRecurse
that
is the generalized mul
function
but uses recursion
Param | Type |
---|---|
…nums | number |
Example
mulRecurse(1, 2, 4) // 1 * 2 * 4 = 8
number
Write a function minRecurse
that
is the generalized min
function
but uses recursion
Param | Type |
---|---|
…nums | number |
Example
minRecurse(1, 2, 4) // 1
number
Write a function maxRecurse
that
is the generalized max
function
but uses recursion
Param | Type |
---|---|
…nums | number |
Example
maxRecurse(1, 2, 4) // 4
function
Write a function not
that
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 acc
that
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) // 7
let mul = acc(mulb, 1)
mul(1, 2, 4) // 8
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.
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 accRecurse
that
does what acc
does but uses recursion
Param | Type |
---|---|
func | function |
initial | number |
Example
let add = accRecurse(addb, 0)
add(1, 2, 4) // 7
let mul = accRecurse(mulb, 1)
mul(1, 2, 4) // 8
array
Write a function fill
that
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 fillRecurse
that
does what fill
does but uses recursion
Param | Type |
---|---|
num | number |
Example
fillRecurse(3) // [ 3, 3, 3 ]
array
Write a function set
that
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 identityf
that 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 addf
that
adds from two invocations
Param | Type |
---|---|
a | number |
Example
addf(3)(4) // 7
function
Write a function liftf
that
takes a binary function, and
makes it callable with two
invocations
Param | Type |
---|---|
binary | function |
Example
let addf = liftf(addb)
addf(3)(4) // 7
liftf(mulb)(5)(6) // 30
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
Returns: array
- an array containing y
and z
Param | Type |
---|---|
x | number |
y | number |
Example
pure(20, 5) // [ 6, 120 ]
pure(25, 6) // [ 7, 175 ]
function
Write a function curryb
that
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) // 7
curryb(mulb, 5)(6) // 30
function
Write a function curry
that
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 inc
function
Param | Type |
---|---|
x | number |
Example
inc(5) // 6
inc(inc(5)) // 7
function
Write a function twiceUnary
that 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) // 22
let square = twiceUnary(mulb)
square(11) // 121
number
Use the function twiceUnary
to
create the doubl
function
Param | Type |
---|---|
x | number |
Example
doubl(11) // 22
number
Use the function twiceUnary
to
create the square
function
Param | Type |
---|---|
x | number |
Example
square(11) // 121
any
Write a function twice
that
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 reverseb
that
reverses the arguments of a
binary function
Param | Type |
---|---|
binary | function |
Example
let bus = reverseb(subb)
bus(3, 2) // -1
function
Write a function reverse
that
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 composeuTwo
that
takes two unary functions and
returns a unary function that
calls them both
Param | Type |
---|---|
unary1 | function |
unary2 | function |
Example
composeuTwo(doubl, square)(5) // (5 * 2)^2 = 100
any
Write a function composeu
that
is generalized for any amount
of arguments
Param | Type |
---|---|
…funcs | function |
Example
composeu(doubl, square, identity, curry(add, 1, 2))(5) // (5 * 2)^2 + 1 + 2 = 103
function
Write a function composeb
that
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) // (2 + 3) * 7 = 35
function
Write a function composeTwo
that
takes two functions and returns a
function that calls them both
Param | Type |
---|---|
func1 | function |
func2 | function |
Example
composeTwo(add, square)(2, 3, 7, 5) // (2 + 3 + 7 + 5)^2 = 289
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
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 limitb
that 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 limit
that
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 genFrom
that
produces a generator that will
produces a series of values. Follows the iterator protocol for the returned format.
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 genTo
that
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.next().value // 1
index.next().value // 2
index.next().value // undefined
function
Write a function genFromTo
that
produces a generator that will
produce values in a range
Param | Type |
---|---|
start | number |
end | number |
Example
let index = genFromTo(0, 3)
index.next().value // 0
index.next().value // 1
index.next().value // 2
index.next().value // undefined
function
Write a function elementGen
that
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.next().value // 'b'
ele.next().value // 'c'
ele.next().value // undefined
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.
Param | Type |
---|---|
array | array |
gen | function |
Example
let ele = element(['a', 'b', 'c', 'd'])
ele.next().value // 'a'
ele.next().value // 'b'
ele.next().value // 'c'
ele.next().value // 'd'
ele.next().value // undefined
function
Write a function collect
that 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.next().value // 0
col.next().value // 1
col.next().value // undefined
array // [0, 1]
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
Param | Type |
---|---|
gen | function |
predicate | function |
Example
let third = (val) => val % 3 === 0
let fil = filter(genFromTo(0, 5), third)
fil.next().value // 0
fil.next().value // 3
fil.next().value // undefined
function
Write a function filterTail
that 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.next().value // 0
fil.next().value // 3
fil.next().value // undefined
function
Write a function concatTwo
that 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.next().value // 0
con.next().value // 1
con.next().value // 2
con.next().value // 0
con.next().value // 1
con.next().value // undefined
function
Write a function concat
that
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.next().value // 0
con.next().value // 1
con.next().value // 2
con.next().value // 0
con.next().value // 1
con.next().value // 5
con.next().value // 6
con.next().value // undefined
function
Write a function concatTail
that 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.next().value // 0
con.next().value // 1
con.next().value // 2
con.next().value // 0
con.next().value // 1
con.next().value // 5
con.next().value // 6
con.next().value // undefined
function
Write a function gensymf
that
makes a function that generates
unique symbols
Param | Type |
---|---|
symbol | string |
Example
let genG = gensymf('G')
let genH = gensymf('H')
genG.next().value // 'G1'
genH.next().value // 'H1'
genG.next().value // 'G2'
genH.next().value // 'H2'
function
Write a function gensymff
that
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.next().value // 'G1'
genH.next().value // 'H1'
genG.next().value // 'G2'
genH.next().value // 'H2'
function
Write a function fibonaccif
that
returns a generator that will
return the next fibonacci number
Param | Type |
---|---|
first | number |
second | number |
Example
let fib = fibonaccif(0, 1)
fib.next().value // 0
fib.next().value // 1
fib.next().value // 1
fib.next().value // 2
fib.next().value // 3
fib.next().value // 5
fib.next().value // 8
object
Write a function counter
that
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 } = obj
up() // 11
down() // 10
down() // 9
up() // 10
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
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 revocable
that
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 extract
that
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 m
that
takes a value and an
optional source string
and returns them in an
object
Param | Type |
---|---|
value | any |
source | any |
Example
m(1) // {value:1, source:"1"}
m(Math.PI, 'pi') // {value:3.14159..., source:"pi"}
object
Write a function addmTwo
that
adds two m
objects and
returns an m
object
Param | Type |
---|---|
m1 | function |
m2 | function |
Example
addmTwo(m(3), m(4)) // {value:7, source:"(3+4)"}
addmTwo(m(1), m(Math.PI, 'pi')) // {value:4.14159..., source:"(1+pi)"}
object
Write a function addm
that
is generalized for any amount of
arguments
Param | Type |
---|---|
…ms | function |
Example
addm(m(1), m(2), m(4)) // {value:7, source:"(1+2+4)"}
object
Write a function liftmbM
that
takes a binary function and
a string and returns a function
that acts on m
objects
Param | Type |
---|---|
binary | function |
op | string |
Example
let addmb = liftmbM(addb, '+')
addmb(m(3), m(4)) // {value:7, source:"(3+4)"}
liftmbM(mul, '*')(m(3), m(4)) // {value:12, source:"(3*4)"}
object
Write a function liftmb
that
is a modified function liftmbM
that can accept arguments that
are either numbers or m objects
Param | Type |
---|---|
binary | function |
op | string |
Example
let addmb = liftmb(addb, '+')
addmb(3, 4) // {value:7, source:"(3+4)"}
object
Write a function liftm
that
is generalized for any amount of
arguments
Param | Type |
---|---|
func | function |
op | string |
Example
let addm = liftm(add, '+')
addm(m(3), m(4)) // {value:7, source:"(3+4)"}
liftm(mul, '*')(m(3), m(4)) // {value:12, source:"(3*4)"}
any
Write a function exp
that
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 expn
that is a modified exp
that
can evaluate nested array
expressions
Param | Type |
---|---|
value | any |
Example
let nae = [Math.sqrt, [add, [square, 3], [square, 4]]]
expn(nae) // sqrt(((3*3)+(4*4))) === 5
number
| undefined
Write a function addg
that
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 liftg
that
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 arrayg
that
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 continuizeu
that takes a unary function
and returns a function that
takes a callback and an
argument
Param | Type |
---|---|
unary | function |
Example
let sqrtc = continuizeu(Math.sqrt)
sqrtc(console.log, 81) // logs '9'
function
Write a function continuize
that takes a function and
returns a function that
takes a callback and arguments
Param | Type |
---|---|
func | function |
Example
let mullc = continuize(mul)
mullc(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 vector
implementation looks like
something like this:
let 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
?
Example
let v = vector()
v.append(1)
v.append(2)
let internalData = exploitVector(v) // [1, 2]
How would you rewrite vector
to deal
with the issue from above?
Example
let v = vectorSafe()
v.append(1)
v.append(2)
let internalData = exploitVector(v) // undefined
Make a function pubsub
that
makes a publish/subscribe object.
It will reliably deliver all
publications to all subscribers
in the right order.
Example
let ps = pubsub()
ps.subscribe(console.log)
ps.publish('It works!') // logs 'It works!'
array
Make a function mapRecurse
that
performs a transformation for each
element of a given array, recursively
Param | Type |
---|---|
array | array |
callback | function |
Example
mapRecurse([1, 2, 3, 4], (x) => x * 2) // [ 2, 4, 6, 8 ]
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.
Param | Type |
---|---|
array | array |
predicate | function |
Example
filterRecurse([1, 2, 3, 4], (x) => x % 2 === 0) // [ 2, 4 ]