Skip to content

Commit a6c4c9e

Browse files
committed
Initial commit
0 parents  commit a6c4c9e

14 files changed

+486
-0
lines changed

.gitignore

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
.DS_Store
2+
node_modules
3+
npm_debug.log

catch-promise.js

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
'use strict';
2+
3+
const getJSON = require('./get-json');
4+
const doMonad = require('./do-notation');
5+
6+
const baseUrl = 'http://localhost:3000/';
7+
doMonad(function* () {
8+
let api = yield getJSON(baseUrl);
9+
for (let resource of api.resources) {
10+
let data = yield getJSON(baseUrl + resource);
11+
console.log(data);
12+
}
13+
}).catch(e => {
14+
console.log(e);
15+
});

do-maybe.js

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
'use strict';
2+
3+
const { Just, Nothing } = require('./maybe');
4+
const doMonad = require('./do-notation');
5+
6+
Just(5).then(x => (
7+
Just(x + 3)
8+
).then(x => (
9+
Just(x * 4)
10+
)).then(console.log));
11+
12+
doMonad(function* () {
13+
let a = yield Just(5);
14+
let b = yield Just(3);
15+
let c = yield Just(4);
16+
console.log((a + b) * c);
17+
});

do-notation.js

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
'use strict';
2+
3+
module.exports = (generator) => {
4+
let sequence = generator();
5+
return step();
6+
7+
function step(value) {
8+
let result = sequence.next(value);
9+
if (result.done) {
10+
return result.value;
11+
}
12+
return result.value.then(step);
13+
}
14+
};

do-promise.js

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
'use strict';
2+
3+
const getJSON = require('./get-json');
4+
const doMonad = require('./do-notation');
5+
6+
const baseUrl = 'http://localhost:3000/';
7+
doMonad(function* () {
8+
let api = yield getJSON(baseUrl);
9+
for (let resource of api.resources) {
10+
let data = yield getJSON(baseUrl + resource);
11+
console.log(data);
12+
}
13+
});

get-json.js

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
'use strict';
2+
3+
const http = require('http');
4+
5+
module.exports = (url) => {
6+
return new Promise((resolve, reject) => {
7+
http.get(url, res => {
8+
let code = res.statusCode;
9+
if (code !== 200) {
10+
return reject(new Error(`HTTP status code ${code}`));
11+
}
12+
13+
res.on('error', reject);
14+
15+
let chunks = [];
16+
res.on('data', chunk => {
17+
chunks.push(chunk);
18+
});
19+
20+
res.on('end', () => {
21+
let json = Buffer.concat(chunks).toString();
22+
let object = null;
23+
24+
try {
25+
object = JSON.parse(json);
26+
} catch (error) {
27+
return reject(error);
28+
}
29+
30+
resolve(object);
31+
});
32+
});
33+
});
34+
};

maybe-catch.js

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
'use strict';
2+
3+
const doMonad = require('./do-notation');
4+
5+
class Just {
6+
constructor(value) {
7+
this.value = value;
8+
}
9+
10+
then(fn) {
11+
let result = fn(this.value);
12+
if (result instanceof Just ||
13+
result === Nothing) {
14+
return result;
15+
} else {
16+
return new Just(result);
17+
}
18+
}
19+
20+
catch() {
21+
return this;
22+
}
23+
}
24+
25+
const Nothing = {
26+
then() {
27+
return Nothing;
28+
},
29+
30+
catch(callback) {
31+
callback();
32+
return this;
33+
}
34+
};
35+
36+
doMonad(function* () {
37+
let a = yield new Just(5);
38+
let b = yield new Just(3);
39+
let c = yield new Just(4);
40+
console.log((a + b) * c);
41+
}).catch(() => {
42+
console.log('At least one value is not present');
43+
});

maybe.js

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
'use strict';
2+
3+
function Just(value) {
4+
return {
5+
toString() {
6+
return `Just ${value}`;
7+
},
8+
9+
then(fn) {
10+
return fn(value);
11+
}
12+
};
13+
}
14+
15+
const Nothing = {
16+
toString() {
17+
return 'Nothing';
18+
},
19+
20+
then() {
21+
return Nothing;
22+
}
23+
};
24+
25+
module.exports = { Just, Nothing };

presentation.md

Lines changed: 167 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,167 @@
1+
Генераторы в JavaScript. Часть 1
2+
================================
3+
4+
@aqrln
5+
6+
---
7+
8+
### Итерабельные объекты и итераторы в ES6
9+
10+
Среди нововведений в ES6, помимо новых синтаксических конструкций и типов
11+
данных, есть и два новых интерфейса: протокол итерабельных объектов и протокол
12+
итераторов.
13+
14+
MDN:
15+
16+
* [Iterable protocol](https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Iteration_protocols#iterable)
17+
* [Iterator protocol](https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Iteration_protocols#iterator)
18+
19+
---
20+
21+
### Iterable Protocol
22+
23+
```javascript
24+
let myIterable = {
25+
...
26+
27+
[Symbol.iterator]() {
28+
let iterator = ...;
29+
return iterator;
30+
}
31+
32+
...
33+
}
34+
```
35+
36+
---
37+
38+
### Iterator Protocol
39+
40+
```javascript
41+
let iterator = {
42+
...
43+
44+
next() {
45+
// Если ещё остались значения
46+
return {
47+
value: currentValue,
48+
done: false
49+
};
50+
51+
// Если значения закончились
52+
return {
53+
value: undefined,
54+
done: true
55+
}
56+
}
57+
}
58+
```
59+
60+
---
61+
62+
### Примеры итерабельных объектов
63+
64+
* Array
65+
* TypedArray
66+
* String
67+
* Buffer
68+
* Map
69+
* Set
70+
71+
---
72+
73+
### Методы коллекций, которые возвращают итераторы
74+
75+
* keys()
76+
* values()
77+
* entries()
78+
79+
---
80+
81+
### Некоторые функции, которые принимают итерабельные объекты
82+
83+
* Конструкторы новых коллекций в ES6 (Map, Set...)
84+
* Array.from()
85+
* Promise.all(), Promise.race()
86+
87+
---
88+
89+
### Синтаксические конструкции, которые работают с итерабельными объектами
90+
91+
* Цикл for-of
92+
* Spread
93+
* Destructuring assignment
94+
* yield*
95+
96+
---
97+
98+
### Генераторы
99+
100+
Generator function — это функция, возвращающая специальный итератор (generator
101+
object), управляющий её выполнением. Оператор `yield` в теле функции
102+
приостанавливает выполнение, метод `next()` итератора — продолжает.
103+
104+
---
105+
106+
Объекты-генераторы одновременно являются и итерабельными объектами, и
107+
итераторами:
108+
109+
```javascript
110+
> function* generatorFunction() { }
111+
undefined
112+
> let generatorObject = generatorFunction()
113+
undefined
114+
> generatorObject.next
115+
[Function: next]
116+
> generatorObject[Symbol.iterator]() === generatorObject
117+
true
118+
```
119+
120+
---
121+
122+
### Yield
123+
124+
Оператор `yield` служит для двунаправленного обмена данными с генератором.
125+
Значение, стоящее после ключевого слова `yield`, становится текущим значением
126+
итератора, а в метод `next()` опционально можно передать значение, которое
127+
примет yield-выражение.
128+
129+
---
130+
131+
### Yield*
132+
133+
```javascript
134+
yield* from iterable;
135+
```
136+
137+
####
138+
139+
```javascript
140+
for (let value of iterable) {
141+
yield value;
142+
}
143+
```
144+
145+
---
146+
147+
### Yield* Expression
148+
149+
```javascript
150+
function* g1() {
151+
yield* [1, 2, 3];
152+
return 'result';
153+
}
154+
155+
let result = null;
156+
157+
function* g2() {
158+
result = yield* g1();
159+
}
160+
161+
console.log([...g2()]); // [1, 2, 3]
162+
console.log(result); // 'result'
163+
```
164+
165+
---
166+
167+
# Q&A

primes.js

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
'use strict';
2+
3+
function* numbers(start) {
4+
while (true) {
5+
yield start++;
6+
}
7+
}
8+
9+
function* sieve(sequence, prime) {
10+
for (let number of sequence) {
11+
if (number % prime !== 0) {
12+
yield number;
13+
}
14+
}
15+
}
16+
17+
function* primes() {
18+
var sequence = numbers(2);
19+
while (true) {
20+
let prime = sequence.next().value;
21+
yield prime;
22+
sequence = sieve(sequence, prime);
23+
}
24+
}
25+
26+
function* take(count, sequence) {
27+
for (let i = 0; i < count; i++) {
28+
yield sequence.next().value;
29+
}
30+
}
31+
32+
for (var prime of take(10, primes())) {
33+
console.log(prime);
34+
}

0 commit comments

Comments
 (0)