Skip to content

Commit d1b1c67

Browse files
authored
Make random() iterable (#24)
1 parent 3b02482 commit d1b1c67

File tree

8 files changed

+81
-14
lines changed

8 files changed

+81
-14
lines changed

.github/workflows/main.yml

-1
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,6 @@ jobs:
1111
matrix:
1212
node-version:
1313
- 14
14-
- 12
1514
steps:
1615
- uses: actions/checkout@v2
1716
- uses: actions/setup-node@v2

assert-in-range.js

+9
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
import chalk from 'chalk';
2+
import inRange from 'in-range';
3+
4+
export default function assertInRange(t, value, {start = 0, end}) {
5+
t.true(
6+
inRange(value, {start, end}),
7+
`${start} ${start <= value ? '≤' : chalk.red('≰')} ${chalk.yellow(value)} ${value <= end ? '≤' : chalk.red('≰')} ${end}`
8+
);
9+
}

index.d.ts

+18-2
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
/**
22
Generate random numbers that are consecutively unique.
33
4-
@returns A function, that when called, will return a random number that is never the same as the previous.
4+
@returns Returns a function, that when called, will return a random number that is never the same as the previous. The returned function is also an iterable which consumes from the same source as the function.
55
66
@example
77
```
@@ -12,5 +12,21 @@ const random = uniqueRandom(1, 10);
1212
console.log(random(), random(), random());
1313
//=> 5 2 6
1414
```
15+
16+
@example
17+
```
18+
import uniqueRandom from 'unique-random';
19+
20+
const random = uniqueRandom(1, 10);
21+
22+
for (const number of random) {
23+
console.log(number);
24+
25+
// The unique numbers will be iterated over infinitely
26+
if (stopCondition) {
27+
break;
28+
}
29+
}
30+
```
1531
*/
16-
export default function uniqueRandom(minimum: number, maximum: number): () => number;
32+
export default function uniqueRandom(minimum: number, maximum: number): (() => number) & {[Symbol.iterator](): Iterator<number>};

index.js

+9-1
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,21 @@
11
export default function uniqueRandom(minimum, maximum) {
22
let previousValue;
33

4-
return function random() {
4+
function random() {
55
const number = Math.floor(
66
(Math.random() * (maximum - minimum + 1)) + minimum
77
);
88

99
previousValue = number === previousValue && minimum !== maximum ? random() : number;
1010

1111
return previousValue;
12+
}
13+
14+
random[Symbol.iterator] = function * () {
15+
while (true) {
16+
yield random();
17+
}
1218
};
19+
20+
return random;
1321
}

index.test-d.ts

+6-2
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,11 @@
1-
import {expectType} from 'tsd';
1+
import {expectAssignable, expectType} from 'tsd';
22
import uniqueRandom from './index.js';
33

44
const random = uniqueRandom(1, 10);
55

6-
expectType<() => number>(random);
6+
expectAssignable<() => number>(random);
77
expectType<number>(random());
8+
9+
for (const number of random) {
10+
expectType<number>(number);
11+
}

package.json

+3-1
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,9 @@
3333
],
3434
"devDependencies": {
3535
"ava": "^3.15.0",
36-
"tsd": "^0.14.0",
36+
"chalk": "^5.3.0",
37+
"in-range": "^3.0.0",
38+
"tsd": "^0.30.7",
3739
"xo": "^0.38.2"
3840
}
3941
}

readme.md

+16-1
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,22 @@ console.log(random(), random(), random());
2525

2626
### uniqueRandom(minimum, maximum)
2727

28-
Returns a function, that when called, will return a random number that is never the same as the previous.
28+
Returns a function, that when called, will return a random number that is never the same as the previous. The returned function is also an iterable which consumes from the same source as the function.
29+
30+
```js
31+
import uniqueRandom from 'unique-random';
32+
33+
const random = uniqueRandom(1, 10);
34+
35+
for (const number of random) {
36+
console.log(number);
37+
38+
// The unique numbers will be iterated over infinitely
39+
if (stopCondition) {
40+
break;
41+
}
42+
}
43+
```
2944

3045
## Related
3146

test.js

+20-6
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import test from 'ava';
2+
import assertInRange from './assert-in-range.js';
23
import uniqueRandom from './index.js';
34

45
test('main', t => {
@@ -10,16 +11,29 @@ test('main', t => {
1011
while (--count > 0) {
1112
currentValue = random();
1213

13-
if (
14-
currentValue === previousValue ||
15-
currentValue > 10 ||
16-
currentValue < 1
17-
) {
18-
t.fail();
14+
assertInRange(t, currentValue, {start: 1, end: 10});
15+
if (previousValue !== undefined) {
16+
t.not(currentValue, previousValue);
1917
}
2018

2119
previousValue = currentValue;
2220
}
2321

2422
t.pass();
2523
});
24+
25+
test('iterator', t => {
26+
t.plan(3); // In case the for-of loop doesn't run
27+
28+
const random = uniqueRandom(1, 10);
29+
30+
for (const number of random) { // eslint-disable-line no-unreachable-loop
31+
assertInRange(t, number, {start: 1, end: 10});
32+
break;
33+
}
34+
35+
const {value, done} = random[Symbol.iterator]().next();
36+
37+
assertInRange(t, value, {start: 1, end: 10});
38+
t.false(done);
39+
});

0 commit comments

Comments
 (0)