-
Notifications
You must be signed in to change notification settings - Fork 7
/
jasper.asks.mjs
128 lines (109 loc) · 3.38 KB
/
jasper.asks.mjs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
// TODO: add a new ask to test for
// generator ???
// recursion ???
const asks = [
[
"Call jasper with one argument: 'start'.",
"Executing functions - call the jasper function passing a string.\n" +
"All of the exercises will require you to call the 'jasper' function.",
function (str) {
return "start" === str;
},
],
[
"Pass in a function that returns true.",
"Higher order functions - functions as arguments.",
function (cb) {
return true === cb();
},
],
[
"Provide an object with two properties: 'a' and 'b'.",
"Object Literals - create a simple object with two properties.",
function (obj) {
return void 0 !== obj.a && void 0 !== obj.b;
},
],
[
"Provide a function that throws an error with message 'down'",
"Errors - throw an Error instance.",
function (fn) {
try {
fn();
} catch (e) {
return "down" === e.message && e instanceof Error;
}
return false;
},
],
[
"Send a JSON string that has a property 'do' with the value 'good'",
"Data interchange format - create a valid JSON string.",
function (json) {
return "good" === JSON.parse(json)["do"];
},
],
[
"Write a function to sum any number of arguments.",
"Use the rest operator, or the 'arguments' object like an array to loop over multiple arguments.",
function (fn) {
const randomInt = (limit = 32) => ~~(Math.random() * limit);
const length = randomInt() + 3;
const [sum, args] = Array(length)
.fill(0)
.reduce(
([sum, args]) => {
const num = randomInt(1024);
return [sum + num, args.concat(num)];
},
[0, []],
);
return sum === fn.apply(null, args);
},
],
[
"Write a function that takes an argument and returns a function that returns that argument.",
"Closures - use a closure to return a value scoped to a newly constructed function; loosely similar to currying.",
function (fn) {
return [42, "good stuff", /asdf/].reduce(function (acc, arg) {
return acc && fn(arg)() === arg;
}, true);
},
],
[
"Execute jasper with a context that matches its argument.",
"Function context - the 'this' keyword is the context of function execution; there are three methods for altering this.",
function (arg) {
return this == arg;
},
],
[
"Add a 'jasper' method to the prototype of the object passed to the function you provide.",
"Prototype chain - methods on the prototype of an object are available to all instances.",
function (fn) {
function F() {}
var obj = new F();
fn(F);
return (
obj.jasper &&
/function/i.test({}.toString.call(obj.jasper)) &&
!obj.hasOwnProperty("jasper")
);
},
],
[
"Pass in a function that will return a Promise; the Promise should reject if the function argument is falsey and resolve if truthy.",
"Promises - async operations accept callbacks for resolved (`.then`) and rejected (`.catch`) statuses.",
function (fn) {
const run = (ans) =>
fn(ans)
.then(() => true)
.catch(() => false)
.then((result) => ans === result);
return Promise.all([run(true), run(false)]).then((all) =>
all.every((result) => true === result),
);
},
],
];
export { asks };